diff --git a/create_db.sql b/create_db.sql
index 9cba9c5ab8c5e0c08f1870f6d74f34f8ac64ba15..2755e794420a7ee413c7880a1e9e3cbee748904e 100644
--- a/create_db.sql
+++ b/create_db.sql
@@ -1,9 +1,14 @@
 CREATE DATABASE store;
+
 USE store;
-CREATE TABLE items (product_id INT AUTO_INCREMENT,name VARCHAR(50),price DECIMAL(5, 2),
-                    imageURL VARCHAR(255),title VARCHAR(50), username VARCHAR(50) unsigned,PRIMARY KEY(id));
+
+CREATE TABLE items (product_id INT AUTO_INCREMENT primary key,title VARCHAR(50),name VARCHAR(50), 
+					price DECIMAL(5, 2), info TEXT , condi VARCHAR(50),img LONGTEXT);
+
 CREATE TABLE userdata (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50), 
                         firstname VARCHAR(50), lastname VARCHAR(50),email VARCHAR(255) NOT NULL UNIQUE,
                         hashedPassword VARCHAR(255) UNIQUE);
-INSERT INTO userdata (username, firstname,lastname,email,hashedPassword)
-                    VALUES('james007',"James","Bond","james007@gmail.com","*%$&23cf£^13!&!*" );
+
+
+CREATE USER 'c'@'localhost' IDENTIFIED WITH mysql_native_password BY 'c';
+GRANT ALL PRIVILEGES ON store.* TO 'c'@'localhost';
diff --git a/index.js b/index.js
index 94307da160a13687c368f8dc4613c6d9e4ef8ddb..3984aec064061842618c138e4cccfb4f6f756ff8 100644
--- a/index.js
+++ b/index.js
@@ -7,15 +7,14 @@ const mysql = require('mysql');
 var validator = require ('express-validator');
 const expressSanitizer = require('express-sanitizer');
 
-//test
-// Create the express application object
 
 
+// Create the express application object
 
-const app = express()
-const port = 8000
+const app = express();
+const port = 8000;
 app.use(expressSanitizer());
-app.use(bodyParser.urlencoded({ extended: true }))
+app.use(bodyParser.urlencoded({ extended: true }));
 
 
 // Create a session
@@ -40,9 +39,9 @@ app.use(express.static(__dirname + "/js"));
 // Define the database connection
 const db = mysql.createConnection ({
     host: 'localhost',
-    user: 'appuser',
-    password: 'app2027',
-    database: 'mybookshop'
+    user: 'c',
+    password: 'c',
+    database: 'store'
 });
 
 // Connect to the database
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
index 2a9f9c2d8cde7b4b539a2cea6e48dc1f9af7d81d..005dad9a75411ba8b020193883b91286a349bd02 100644
--- a/node_modules/.package-lock.json
+++ b/node_modules/.package-lock.json
@@ -123,16 +123,24 @@
       }
     },
     "node_modules/ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
       "dependencies": {
-        "color-convert": "^1.9.0"
+        "color-convert": "^2.0.1"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
+    "node_modules/append-field": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
+      "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
+    },
     "node_modules/aproba": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
@@ -179,9 +187,9 @@
       "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw=="
     },
     "node_modules/async": {
-      "version": "0.9.2",
-      "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
-      "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
+      "version": "3.2.4",
+      "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+      "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
     },
     "node_modules/babel-walk": {
       "version": "3.0.0-canary-5",
@@ -252,6 +260,22 @@
         "concat-map": "0.0.1"
       }
     },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+    },
+    "node_modules/busboy": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+      "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+      "dependencies": {
+        "streamsearch": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=10.16.0"
+      }
+    },
     "node_modules/bytes": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -273,16 +297,18 @@
       }
     },
     "node_modules/chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
       "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
     "node_modules/character-parser": {
@@ -302,17 +328,20 @@
       }
     },
     "node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
       "dependencies": {
-        "color-name": "1.1.3"
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
       }
     },
     "node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
     },
     "node_modules/color-support": {
       "version": "1.1.3",
@@ -327,6 +356,20 @@
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
+    "node_modules/concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "engines": [
+        "node >= 0.8"
+      ],
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
     "node_modules/console-control-strings": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -446,11 +489,11 @@
       "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
     },
     "node_modules/ejs": {
-      "version": "3.1.6",
-      "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
-      "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
+      "version": "3.1.9",
+      "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
+      "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
       "dependencies": {
-        "jake": "^10.6.1"
+        "jake": "^10.8.5"
       },
       "bin": {
         "ejs": "bin/cli.js"
@@ -477,14 +520,6 @@
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
       "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
     },
-    "node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
     "node_modules/etag": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -622,11 +657,30 @@
       ]
     },
     "node_modules/filelist": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
-      "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+      "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
       "dependencies": {
-        "minimatch": "^3.0.4"
+        "minimatch": "^5.0.1"
+      }
+    },
+    "node_modules/filelist/node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/filelist/node_modules/minimatch": {
+      "version": "5.1.6",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+      "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=10"
       }
     },
     "node_modules/finalhandler": {
@@ -746,11 +800,11 @@
       }
     },
     "node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
       }
     },
     "node_modules/has-symbols": {
@@ -918,12 +972,12 @@
       "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
     },
     "node_modules/jake": {
-      "version": "10.8.2",
-      "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
-      "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
+      "version": "10.8.5",
+      "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+      "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
       "dependencies": {
-        "async": "0.9.x",
-        "chalk": "^2.4.2",
+        "async": "^3.2.3",
+        "chalk": "^4.0.2",
         "filelist": "^1.0.1",
         "minimatch": "^3.0.4"
       },
@@ -931,7 +985,7 @@
         "jake": "bin/cli.js"
       },
       "engines": {
-        "node": "*"
+        "node": ">=10"
       }
     },
     "node_modules/js-stringify": {
@@ -1048,6 +1102,14 @@
         "node": "*"
       }
     },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/minipass": {
       "version": "3.3.4",
       "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz",
@@ -1087,6 +1149,34 @@
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
     },
+    "node_modules/multer": {
+      "version": "1.4.5-lts.1",
+      "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
+      "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
+      "dependencies": {
+        "append-field": "^1.0.0",
+        "busboy": "^1.0.0",
+        "concat-stream": "^1.5.2",
+        "mkdirp": "^0.5.4",
+        "object-assign": "^4.1.1",
+        "type-is": "^1.6.4",
+        "xtend": "^4.0.0"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/multer/node_modules/mkdirp": {
+      "version": "0.5.6",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+      "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+      "dependencies": {
+        "minimist": "^1.2.6"
+      },
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      }
+    },
     "node_modules/mysql": {
       "version": "2.18.1",
       "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
@@ -1613,6 +1703,14 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/streamsearch": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+      "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
     "node_modules/string_decoder": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -1646,14 +1744,14 @@
       }
     },
     "node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
       "dependencies": {
-        "has-flag": "^3.0.0"
+        "has-flag": "^4.0.0"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
       }
     },
     "node_modules/tar": {
@@ -1710,6 +1808,11 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+    },
     "node_modules/uid-safe": {
       "version": "2.1.5",
       "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
@@ -1815,6 +1918,14 @@
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
     },
+    "node_modules/xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+      "engines": {
+        "node": ">=0.4"
+      }
+    },
     "node_modules/yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
diff --git a/node_modules/ansi-styles/index.d.ts b/node_modules/ansi-styles/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..44a907e580f1055a36d44111fda9463ed1cd2d26
--- /dev/null
+++ b/node_modules/ansi-styles/index.d.ts
@@ -0,0 +1,345 @@
+declare type CSSColor =
+	| 'aliceblue'
+	| 'antiquewhite'
+	| 'aqua'
+	| 'aquamarine'
+	| 'azure'
+	| 'beige'
+	| 'bisque'
+	| 'black'
+	| 'blanchedalmond'
+	| 'blue'
+	| 'blueviolet'
+	| 'brown'
+	| 'burlywood'
+	| 'cadetblue'
+	| 'chartreuse'
+	| 'chocolate'
+	| 'coral'
+	| 'cornflowerblue'
+	| 'cornsilk'
+	| 'crimson'
+	| 'cyan'
+	| 'darkblue'
+	| 'darkcyan'
+	| 'darkgoldenrod'
+	| 'darkgray'
+	| 'darkgreen'
+	| 'darkgrey'
+	| 'darkkhaki'
+	| 'darkmagenta'
+	| 'darkolivegreen'
+	| 'darkorange'
+	| 'darkorchid'
+	| 'darkred'
+	| 'darksalmon'
+	| 'darkseagreen'
+	| 'darkslateblue'
+	| 'darkslategray'
+	| 'darkslategrey'
+	| 'darkturquoise'
+	| 'darkviolet'
+	| 'deeppink'
+	| 'deepskyblue'
+	| 'dimgray'
+	| 'dimgrey'
+	| 'dodgerblue'
+	| 'firebrick'
+	| 'floralwhite'
+	| 'forestgreen'
+	| 'fuchsia'
+	| 'gainsboro'
+	| 'ghostwhite'
+	| 'gold'
+	| 'goldenrod'
+	| 'gray'
+	| 'green'
+	| 'greenyellow'
+	| 'grey'
+	| 'honeydew'
+	| 'hotpink'
+	| 'indianred'
+	| 'indigo'
+	| 'ivory'
+	| 'khaki'
+	| 'lavender'
+	| 'lavenderblush'
+	| 'lawngreen'
+	| 'lemonchiffon'
+	| 'lightblue'
+	| 'lightcoral'
+	| 'lightcyan'
+	| 'lightgoldenrodyellow'
+	| 'lightgray'
+	| 'lightgreen'
+	| 'lightgrey'
+	| 'lightpink'
+	| 'lightsalmon'
+	| 'lightseagreen'
+	| 'lightskyblue'
+	| 'lightslategray'
+	| 'lightslategrey'
+	| 'lightsteelblue'
+	| 'lightyellow'
+	| 'lime'
+	| 'limegreen'
+	| 'linen'
+	| 'magenta'
+	| 'maroon'
+	| 'mediumaquamarine'
+	| 'mediumblue'
+	| 'mediumorchid'
+	| 'mediumpurple'
+	| 'mediumseagreen'
+	| 'mediumslateblue'
+	| 'mediumspringgreen'
+	| 'mediumturquoise'
+	| 'mediumvioletred'
+	| 'midnightblue'
+	| 'mintcream'
+	| 'mistyrose'
+	| 'moccasin'
+	| 'navajowhite'
+	| 'navy'
+	| 'oldlace'
+	| 'olive'
+	| 'olivedrab'
+	| 'orange'
+	| 'orangered'
+	| 'orchid'
+	| 'palegoldenrod'
+	| 'palegreen'
+	| 'paleturquoise'
+	| 'palevioletred'
+	| 'papayawhip'
+	| 'peachpuff'
+	| 'peru'
+	| 'pink'
+	| 'plum'
+	| 'powderblue'
+	| 'purple'
+	| 'rebeccapurple'
+	| 'red'
+	| 'rosybrown'
+	| 'royalblue'
+	| 'saddlebrown'
+	| 'salmon'
+	| 'sandybrown'
+	| 'seagreen'
+	| 'seashell'
+	| 'sienna'
+	| 'silver'
+	| 'skyblue'
+	| 'slateblue'
+	| 'slategray'
+	| 'slategrey'
+	| 'snow'
+	| 'springgreen'
+	| 'steelblue'
+	| 'tan'
+	| 'teal'
+	| 'thistle'
+	| 'tomato'
+	| 'turquoise'
+	| 'violet'
+	| 'wheat'
+	| 'white'
+	| 'whitesmoke'
+	| 'yellow'
+	| 'yellowgreen';
+
+declare namespace ansiStyles {
+	interface ColorConvert {
+		/**
+		The RGB color space.
+
+		@param red - (`0`-`255`)
+		@param green - (`0`-`255`)
+		@param blue - (`0`-`255`)
+		*/
+		rgb(red: number, green: number, blue: number): string;
+
+		/**
+		The RGB HEX color space.
+
+		@param hex - A hexadecimal string containing RGB data.
+		*/
+		hex(hex: string): string;
+
+		/**
+		@param keyword - A CSS color name.
+		*/
+		keyword(keyword: CSSColor): string;
+
+		/**
+		The HSL color space.
+
+		@param hue - (`0`-`360`)
+		@param saturation - (`0`-`100`)
+		@param lightness - (`0`-`100`)
+		*/
+		hsl(hue: number, saturation: number, lightness: number): string;
+
+		/**
+		The HSV color space.
+
+		@param hue - (`0`-`360`)
+		@param saturation - (`0`-`100`)
+		@param value - (`0`-`100`)
+		*/
+		hsv(hue: number, saturation: number, value: number): string;
+
+		/**
+		The HSV color space.
+
+		@param hue - (`0`-`360`)
+		@param whiteness - (`0`-`100`)
+		@param blackness - (`0`-`100`)
+		*/
+		hwb(hue: number, whiteness: number, blackness: number): string;
+
+		/**
+		Use a [4-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4-bit) to set text color.
+		*/
+		ansi(ansi: number): string;
+
+		/**
+		Use an [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
+		*/
+		ansi256(ansi: number): string;
+	}
+
+	interface CSPair {
+		/**
+		The ANSI terminal control sequence for starting this style.
+		*/
+		readonly open: string;
+
+		/**
+		The ANSI terminal control sequence for ending this style.
+		*/
+		readonly close: string;
+	}
+
+	interface ColorBase {
+		readonly ansi: ColorConvert;
+		readonly ansi256: ColorConvert;
+		readonly ansi16m: ColorConvert;
+
+		/**
+		The ANSI terminal control sequence for ending this color.
+		*/
+		readonly close: string;
+	}
+
+	interface Modifier {
+		/**
+		Resets the current color chain.
+		*/
+		readonly reset: CSPair;
+
+		/**
+		Make text bold.
+		*/
+		readonly bold: CSPair;
+
+		/**
+		Emitting only a small amount of light.
+		*/
+		readonly dim: CSPair;
+
+		/**
+		Make text italic. (Not widely supported)
+		*/
+		readonly italic: CSPair;
+
+		/**
+		Make text underline. (Not widely supported)
+		*/
+		readonly underline: CSPair;
+
+		/**
+		Inverse background and foreground colors.
+		*/
+		readonly inverse: CSPair;
+
+		/**
+		Prints the text, but makes it invisible.
+		*/
+		readonly hidden: CSPair;
+
+		/**
+		Puts a horizontal line through the center of the text. (Not widely supported)
+		*/
+		readonly strikethrough: CSPair;
+	}
+
+	interface ForegroundColor {
+		readonly black: CSPair;
+		readonly red: CSPair;
+		readonly green: CSPair;
+		readonly yellow: CSPair;
+		readonly blue: CSPair;
+		readonly cyan: CSPair;
+		readonly magenta: CSPair;
+		readonly white: CSPair;
+
+		/**
+		Alias for `blackBright`.
+		*/
+		readonly gray: CSPair;
+
+		/**
+		Alias for `blackBright`.
+		*/
+		readonly grey: CSPair;
+
+		readonly blackBright: CSPair;
+		readonly redBright: CSPair;
+		readonly greenBright: CSPair;
+		readonly yellowBright: CSPair;
+		readonly blueBright: CSPair;
+		readonly cyanBright: CSPair;
+		readonly magentaBright: CSPair;
+		readonly whiteBright: CSPair;
+	}
+
+	interface BackgroundColor {
+		readonly bgBlack: CSPair;
+		readonly bgRed: CSPair;
+		readonly bgGreen: CSPair;
+		readonly bgYellow: CSPair;
+		readonly bgBlue: CSPair;
+		readonly bgCyan: CSPair;
+		readonly bgMagenta: CSPair;
+		readonly bgWhite: CSPair;
+
+		/**
+		Alias for `bgBlackBright`.
+		*/
+		readonly bgGray: CSPair;
+
+		/**
+		Alias for `bgBlackBright`.
+		*/
+		readonly bgGrey: CSPair;
+
+		readonly bgBlackBright: CSPair;
+		readonly bgRedBright: CSPair;
+		readonly bgGreenBright: CSPair;
+		readonly bgYellowBright: CSPair;
+		readonly bgBlueBright: CSPair;
+		readonly bgCyanBright: CSPair;
+		readonly bgMagentaBright: CSPair;
+		readonly bgWhiteBright: CSPair;
+	}
+}
+
+declare const ansiStyles: {
+	readonly modifier: ansiStyles.Modifier;
+	readonly color: ansiStyles.ForegroundColor & ansiStyles.ColorBase;
+	readonly bgColor: ansiStyles.BackgroundColor & ansiStyles.ColorBase;
+	readonly codes: ReadonlyMap<number, number>;
+} & ansiStyles.BackgroundColor & ansiStyles.ForegroundColor & ansiStyles.Modifier;
+
+export = ansiStyles;
diff --git a/node_modules/ansi-styles/index.js b/node_modules/ansi-styles/index.js
index 90a871c4d78f6f588a3a477d36f4352922989fa6..5d82581a13f9900f9dc653b2df9f0027ee8bdda1 100644
--- a/node_modules/ansi-styles/index.js
+++ b/node_modules/ansi-styles/index.js
@@ -1,21 +1,63 @@
 'use strict';
-const colorConvert = require('color-convert');
 
-const wrapAnsi16 = (fn, offset) => function () {
-	const code = fn.apply(colorConvert, arguments);
+const wrapAnsi16 = (fn, offset) => (...args) => {
+	const code = fn(...args);
 	return `\u001B[${code + offset}m`;
 };
 
-const wrapAnsi256 = (fn, offset) => function () {
-	const code = fn.apply(colorConvert, arguments);
+const wrapAnsi256 = (fn, offset) => (...args) => {
+	const code = fn(...args);
 	return `\u001B[${38 + offset};5;${code}m`;
 };
 
-const wrapAnsi16m = (fn, offset) => function () {
-	const rgb = fn.apply(colorConvert, arguments);
+const wrapAnsi16m = (fn, offset) => (...args) => {
+	const rgb = fn(...args);
 	return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
 };
 
+const ansi2ansi = n => n;
+const rgb2rgb = (r, g, b) => [r, g, b];
+
+const setLazyProperty = (object, property, get) => {
+	Object.defineProperty(object, property, {
+		get: () => {
+			const value = get();
+
+			Object.defineProperty(object, property, {
+				value,
+				enumerable: true,
+				configurable: true
+			});
+
+			return value;
+		},
+		enumerable: true,
+		configurable: true
+	});
+};
+
+/** @type {typeof import('color-convert')} */
+let colorConvert;
+const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => {
+	if (colorConvert === undefined) {
+		colorConvert = require('color-convert');
+	}
+
+	const offset = isBackground ? 10 : 0;
+	const styles = {};
+
+	for (const [sourceSpace, suite] of Object.entries(colorConvert)) {
+		const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace;
+		if (sourceSpace === targetSpace) {
+			styles[name] = wrap(identity, offset);
+		} else if (typeof suite === 'object') {
+			styles[name] = wrap(suite[targetSpace], offset);
+		}
+	}
+
+	return styles;
+};
+
 function assembleStyles() {
 	const codes = new Map();
 	const styles = {
@@ -39,9 +81,9 @@ function assembleStyles() {
 			magenta: [35, 39],
 			cyan: [36, 39],
 			white: [37, 39],
-			gray: [90, 39],
 
 			// Bright color
+			blackBright: [90, 39],
 			redBright: [91, 39],
 			greenBright: [92, 39],
 			yellowBright: [93, 39],
@@ -72,15 +114,14 @@ function assembleStyles() {
 		}
 	};
 
-	// Fix humans
-	styles.color.grey = styles.color.gray;
-
-	for (const groupName of Object.keys(styles)) {
-		const group = styles[groupName];
-
-		for (const styleName of Object.keys(group)) {
-			const style = group[styleName];
+	// Alias bright black as gray (and grey)
+	styles.color.gray = styles.color.blackBright;
+	styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
+	styles.color.grey = styles.color.blackBright;
+	styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;
 
+	for (const [groupName, group] of Object.entries(styles)) {
+		for (const [styleName, style] of Object.entries(group)) {
 			styles[styleName] = {
 				open: `\u001B[${style[0]}m`,
 				close: `\u001B[${style[1]}m`
@@ -95,65 +136,22 @@ function assembleStyles() {
 			value: group,
 			enumerable: false
 		});
-
-		Object.defineProperty(styles, 'codes', {
-			value: codes,
-			enumerable: false
-		});
 	}
 
-	const ansi2ansi = n => n;
-	const rgb2rgb = (r, g, b) => [r, g, b];
+	Object.defineProperty(styles, 'codes', {
+		value: codes,
+		enumerable: false
+	});
 
 	styles.color.close = '\u001B[39m';
 	styles.bgColor.close = '\u001B[49m';
 
-	styles.color.ansi = {
-		ansi: wrapAnsi16(ansi2ansi, 0)
-	};
-	styles.color.ansi256 = {
-		ansi256: wrapAnsi256(ansi2ansi, 0)
-	};
-	styles.color.ansi16m = {
-		rgb: wrapAnsi16m(rgb2rgb, 0)
-	};
-
-	styles.bgColor.ansi = {
-		ansi: wrapAnsi16(ansi2ansi, 10)
-	};
-	styles.bgColor.ansi256 = {
-		ansi256: wrapAnsi256(ansi2ansi, 10)
-	};
-	styles.bgColor.ansi16m = {
-		rgb: wrapAnsi16m(rgb2rgb, 10)
-	};
-
-	for (let key of Object.keys(colorConvert)) {
-		if (typeof colorConvert[key] !== 'object') {
-			continue;
-		}
-
-		const suite = colorConvert[key];
-
-		if (key === 'ansi16') {
-			key = 'ansi';
-		}
-
-		if ('ansi16' in suite) {
-			styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0);
-			styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10);
-		}
-
-		if ('ansi256' in suite) {
-			styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0);
-			styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10);
-		}
-
-		if ('rgb' in suite) {
-			styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0);
-			styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10);
-		}
-	}
+	setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false));
+	setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false));
+	setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false));
+	setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true));
+	setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true));
+	setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true));
 
 	return styles;
 }
diff --git a/node_modules/ansi-styles/package.json b/node_modules/ansi-styles/package.json
index 65edb48c399c5ceffe281ba0a6dd3e09fa4b5dd6..75393284d7e474de2c7fb1ee7d09169a6790c7da 100644
--- a/node_modules/ansi-styles/package.json
+++ b/node_modules/ansi-styles/package.json
@@ -1,23 +1,25 @@
 {
 	"name": "ansi-styles",
-	"version": "3.2.1",
+	"version": "4.3.0",
 	"description": "ANSI escape codes for styling strings in the terminal",
 	"license": "MIT",
 	"repository": "chalk/ansi-styles",
+	"funding": "https://github.com/chalk/ansi-styles?sponsor=1",
 	"author": {
 		"name": "Sindre Sorhus",
 		"email": "sindresorhus@gmail.com",
 		"url": "sindresorhus.com"
 	},
 	"engines": {
-		"node": ">=4"
+		"node": ">=8"
 	},
 	"scripts": {
-		"test": "xo && ava",
+		"test": "xo && ava && tsd",
 		"screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"
 	},
 	"files": [
-		"index.js"
+		"index.js",
+		"index.d.ts"
 	],
 	"keywords": [
 		"ansi",
@@ -42,15 +44,13 @@
 		"text"
 	],
 	"dependencies": {
-		"color-convert": "^1.9.0"
+		"color-convert": "^2.0.1"
 	},
 	"devDependencies": {
-		"ava": "*",
-		"babel-polyfill": "^6.23.0",
+		"@types/color-convert": "^1.9.0",
+		"ava": "^2.3.0",
 		"svg-term-cli": "^2.1.1",
-		"xo": "*"
-	},
-	"ava": {
-		"require": "babel-polyfill"
+		"tsd": "^0.11.0",
+		"xo": "^0.25.3"
 	}
 }
diff --git a/node_modules/ansi-styles/readme.md b/node_modules/ansi-styles/readme.md
index 3158e2df59ce6637302d017d795492c1c3cef1c0..24883de808be6a7480542114a86034312c026dec 100644
--- a/node_modules/ansi-styles/readme.md
+++ b/node_modules/ansi-styles/readme.md
@@ -1,11 +1,10 @@
 # ansi-styles [![Build Status](https://travis-ci.org/chalk/ansi-styles.svg?branch=master)](https://travis-ci.org/chalk/ansi-styles)
 
-> [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
+> [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
 
 You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.
 
-<img src="https://cdn.rawgit.com/chalk/ansi-styles/8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
-
+<img src="screenshot.svg" width="900">
 
 ## Install
 
@@ -13,7 +12,6 @@ You probably want the higher-level [chalk](https://github.com/chalk/chalk) modul
 $ npm install ansi-styles
 ```
 
-
 ## Usage
 
 ```js
@@ -29,14 +27,13 @@ console.log(`${style.green.open}Hello world!${style.green.close}`);
 //       original color.
 console.log(style.bgColor.ansi.hsl(120, 80, 72) + 'Hello world!' + style.bgColor.close);
 console.log(style.color.ansi256.rgb(199, 20, 250) + 'Hello world!' + style.color.close);
-console.log(style.color.ansi16m.hex('#ABCDEF') + 'Hello world!' + style.color.close);
+console.log(style.color.ansi16m.hex('#abcdef') + 'Hello world!' + style.color.close);
 ```
 
 ## API
 
 Each style has an `open` and `close` property.
 
-
 ## Styles
 
 ### Modifiers
@@ -60,7 +57,7 @@ Each style has an `open` and `close` property.
 - `magenta`
 - `cyan`
 - `white`
-- `gray` ("bright black")
+- `blackBright` (alias: `gray`, `grey`)
 - `redBright`
 - `greenBright`
 - `yellowBright`
@@ -79,7 +76,7 @@ Each style has an `open` and `close` property.
 - `bgMagenta`
 - `bgCyan`
 - `bgWhite`
-- `bgBlackBright`
+- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
 - `bgRedBright`
 - `bgGreenBright`
 - `bgYellowBright`
@@ -88,7 +85,6 @@ Each style has an `open` and `close` property.
 - `bgCyanBright`
 - `bgWhiteBright`
 
-
 ## Advanced usage
 
 By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.
@@ -112,11 +108,21 @@ console.log(style.codes.get(36));
 //=> 39
 ```
 
-
 ## [256 / 16 million (TrueColor) support](https://gist.github.com/XVilka/8346728)
 
 `ansi-styles` uses the [`color-convert`](https://github.com/Qix-/color-convert) package to allow for converting between various colors and ANSI escapes, with support for 256 and 16 million colors.
 
+The following color spaces from `color-convert` are supported:
+
+- `rgb`
+- `hex`
+- `keyword`
+- `hsl`
+- `hsv`
+- `hwb`
+- `ansi`
+- `ansi256`
+
 To use these, call the associated conversion function with the intended output, for example:
 
 ```js
@@ -130,18 +136,17 @@ style.color.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color foreground
 style.bgColor.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color background code
 ```
 
-
 ## Related
 
 - [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal
 
-
 ## Maintainers
 
 - [Sindre Sorhus](https://github.com/sindresorhus)
 - [Josh Junon](https://github.com/qix-)
 
+## For enterprise
 
-## License
+Available as part of the Tidelift Subscription.
 
-MIT
+The maintainers of `ansi-styles` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-ansi-styles?utm_source=npm-ansi-styles&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
diff --git a/node_modules/append-field/.npmignore b/node_modules/append-field/.npmignore
new file mode 100644
index 0000000000000000000000000000000000000000..c2658d7d1b31848c3b71960543cb0368e56cd4c7
--- /dev/null
+++ b/node_modules/append-field/.npmignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/node_modules/append-field/LICENSE b/node_modules/append-field/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..14b1f891b40cc88122b238cdfb966124d7268084
--- /dev/null
+++ b/node_modules/append-field/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Linus Unnebäck
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/append-field/README.md b/node_modules/append-field/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..62b901b7e8c1f92f113ad0bc728aed6595ee7a13
--- /dev/null
+++ b/node_modules/append-field/README.md
@@ -0,0 +1,44 @@
+# `append-field`
+
+A [W3C HTML JSON forms spec](http://www.w3.org/TR/html-json-forms/) compliant
+field appender (for lack of a better name). Useful for people implementing
+`application/x-www-form-urlencoded` and `multipart/form-data` parsers.
+
+It works best on objects created with `Object.create(null)`. Otherwise it might
+conflict with variables from the prototype (e.g. `hasOwnProperty`).
+
+## Installation
+
+```sh
+npm install --save append-field
+```
+
+## Usage
+
+```javascript
+var appendField = require('append-field')
+var obj = Object.create(null)
+
+appendField(obj, 'pets[0][species]', 'Dahut')
+appendField(obj, 'pets[0][name]', 'Hypatia')
+appendField(obj, 'pets[1][species]', 'Felis Stultus')
+appendField(obj, 'pets[1][name]', 'Billie')
+
+console.log(obj)
+```
+
+```text
+{ pets:
+   [ { species: 'Dahut', name: 'Hypatia' },
+     { species: 'Felis Stultus', name: 'Billie' } ] }
+```
+
+## API
+
+### `appendField(store, key, value)`
+
+Adds the field named `key` with the value `value` to the object `store`.
+
+## License
+
+MIT
diff --git a/node_modules/append-field/index.js b/node_modules/append-field/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..fc5acc8bc41502a08fa7d537987d05b0c7ef5775
--- /dev/null
+++ b/node_modules/append-field/index.js
@@ -0,0 +1,12 @@
+var parsePath = require('./lib/parse-path')
+var setValue = require('./lib/set-value')
+
+function appendField (store, key, value) {
+  var steps = parsePath(key)
+
+  steps.reduce(function (context, step) {
+    return setValue(context, step, context[step.key], value)
+  }, store)
+}
+
+module.exports = appendField
diff --git a/node_modules/append-field/lib/parse-path.js b/node_modules/append-field/lib/parse-path.js
new file mode 100644
index 0000000000000000000000000000000000000000..31d617966f02ca37d98f9caa3ef4779118bbd635
--- /dev/null
+++ b/node_modules/append-field/lib/parse-path.js
@@ -0,0 +1,53 @@
+var reFirstKey = /^[^\[]*/
+var reDigitPath = /^\[(\d+)\]/
+var reNormalPath = /^\[([^\]]+)\]/
+
+function parsePath (key) {
+  function failure () {
+    return [{ type: 'object', key: key, last: true }]
+  }
+
+  var firstKey = reFirstKey.exec(key)[0]
+  if (!firstKey) return failure()
+
+  var len = key.length
+  var pos = firstKey.length
+  var tail = { type: 'object', key: firstKey }
+  var steps = [tail]
+
+  while (pos < len) {
+    var m
+
+    if (key[pos] === '[' && key[pos + 1] === ']') {
+      pos += 2
+      tail.append = true
+      if (pos !== len) return failure()
+      continue
+    }
+
+    m = reDigitPath.exec(key.substring(pos))
+    if (m !== null) {
+      pos += m[0].length
+      tail.nextType = 'array'
+      tail = { type: 'array', key: parseInt(m[1], 10) }
+      steps.push(tail)
+      continue
+    }
+
+    m = reNormalPath.exec(key.substring(pos))
+    if (m !== null) {
+      pos += m[0].length
+      tail.nextType = 'object'
+      tail = { type: 'object', key: m[1] }
+      steps.push(tail)
+      continue
+    }
+
+    return failure()
+  }
+
+  tail.last = true
+  return steps
+}
+
+module.exports = parsePath
diff --git a/node_modules/append-field/lib/set-value.js b/node_modules/append-field/lib/set-value.js
new file mode 100644
index 0000000000000000000000000000000000000000..c15e87377bc84537acdceb74466320644592b72d
--- /dev/null
+++ b/node_modules/append-field/lib/set-value.js
@@ -0,0 +1,64 @@
+function valueType (value) {
+  if (value === undefined) return 'undefined'
+  if (Array.isArray(value)) return 'array'
+  if (typeof value === 'object') return 'object'
+  return 'scalar'
+}
+
+function setLastValue (context, step, currentValue, entryValue) {
+  switch (valueType(currentValue)) {
+    case 'undefined':
+      if (step.append) {
+        context[step.key] = [entryValue]
+      } else {
+        context[step.key] = entryValue
+      }
+      break
+    case 'array':
+      context[step.key].push(entryValue)
+      break
+    case 'object':
+      return setLastValue(currentValue, { type: 'object', key: '', last: true }, currentValue[''], entryValue)
+    case 'scalar':
+      context[step.key] = [context[step.key], entryValue]
+      break
+  }
+
+  return context
+}
+
+function setValue (context, step, currentValue, entryValue) {
+  if (step.last) return setLastValue(context, step, currentValue, entryValue)
+
+  var obj
+  switch (valueType(currentValue)) {
+    case 'undefined':
+      if (step.nextType === 'array') {
+        context[step.key] = []
+      } else {
+        context[step.key] = Object.create(null)
+      }
+      return context[step.key]
+    case 'object':
+      return context[step.key]
+    case 'array':
+      if (step.nextType === 'array') {
+        return currentValue
+      }
+
+      obj = Object.create(null)
+      context[step.key] = obj
+      currentValue.forEach(function (item, i) {
+        if (item !== undefined) obj['' + i] = item
+      })
+
+      return obj
+    case 'scalar':
+      obj = Object.create(null)
+      obj[''] = currentValue
+      context[step.key] = obj
+      return obj
+  }
+}
+
+module.exports = setValue
diff --git a/node_modules/append-field/package.json b/node_modules/append-field/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..8d6e716433ff4f99e99412f2e63523459dc0f9a8
--- /dev/null
+++ b/node_modules/append-field/package.json
@@ -0,0 +1,19 @@
+{
+  "name": "append-field",
+  "version": "1.0.0",
+  "license": "MIT",
+  "author": "Linus Unnebäck <linus@folkdatorn.se>",
+  "main": "index.js",
+  "devDependencies": {
+    "mocha": "^2.2.4",
+    "standard": "^6.0.5",
+    "testdata-w3c-json-form": "^0.2.0"
+  },
+  "scripts": {
+    "test": "standard && mocha"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/LinusU/node-append-field.git"
+  }
+}
diff --git a/node_modules/append-field/test/forms.js b/node_modules/append-field/test/forms.js
new file mode 100644
index 0000000000000000000000000000000000000000..dd6fbc988e8b71f9cc438d5ddf114f8ad704216f
--- /dev/null
+++ b/node_modules/append-field/test/forms.js
@@ -0,0 +1,19 @@
+/* eslint-env mocha */
+
+var assert = require('assert')
+var appendField = require('../')
+var testData = require('testdata-w3c-json-form')
+
+describe('Append Field', function () {
+  for (var test of testData) {
+    it('handles ' + test.name, function () {
+      var store = Object.create(null)
+
+      for (var field of test.fields) {
+        appendField(store, field.key, field.value)
+      }
+
+      assert.deepEqual(store, test.expected)
+    })
+  }
+})
diff --git a/node_modules/async/CHANGELOG.md b/node_modules/async/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..8a9a1bfdcab042081ef5a0794f4efc19cfa26114
--- /dev/null
+++ b/node_modules/async/CHANGELOG.md
@@ -0,0 +1,348 @@
+# v3.2.4
+- Fix a bug in `priorityQueue` where it didn't wait for the result. (#1725)
+- Fix a bug where `unshiftAsync` was included in `priorityQueue`. (#1790)
+
+# v3.2.3
+- Fix bugs in comment parsing in `autoInject`. (#1767, #1780)
+
+# v3.2.2
+- Fix potential prototype pollution exploit
+
+# v3.2.1
+- Use `queueMicrotask` if available to the environment (#1761)
+- Minor perf improvement in `priorityQueue` (#1727)
+- More examples in documentation (#1726)
+- Various doc fixes (#1708, #1712, #1717, #1740, #1739, #1749, #1756)
+- Improved test coverage (#1754)
+
+# v3.2.0
+- Fix a bug in Safari related to overwriting `func.name`
+- Remove built-in browserify configuration (#1653)
+- Varios doc fixes (#1688, #1703, #1704)
+
+# v3.1.1
+- Allow redefining `name` property on wrapped functions.
+
+# v3.1.0
+
+- Added `q.pushAsync` and `q.unshiftAsync`, analagous to `q.push` and `q.unshift`, except they always do not accept a callback, and reject if processing the task errors. (#1659)
+- Promises returned from `q.push` and `q.unshift` when a callback is not passed now resolve even if an error ocurred. (#1659)
+- Fixed a parsing bug in `autoInject` with complicated function bodies (#1663)
+- Added ES6+ configuration for Browserify bundlers (#1653)
+- Various doc fixes (#1664, #1658, #1665, #1652)
+
+# v3.0.1
+
+## Bug fixes
+- Fixed a regression where arrays passed to `queue` and `cargo` would be completely flattened. (#1645)
+- Clarified Async's browser support (#1643)
+
+
+# v3.0.0
+
+The `async`/`await` release!
+
+There are a lot of new features and subtle breaking changes in this major version, but the biggest feature is that most Async methods return a Promise if you omit the callback, meaning you can `await` them from within an `async` function.
+
+```js
+const results = await async.mapLimit(urls, 5, async url => {
+    const resp = await fetch(url)
+    return resp.body
+})
+```
+
+## Breaking Changes
+- Most Async methods return a Promise when the final callback is omitted, making them `await`-able! (#1572)
+- We are now making heavy use of ES2015 features, this means we have dropped out-of-the-box support for Node 4 and earlier, and many old versions of browsers. (#1541, #1553)
+- In `queue`, `priorityQueue`, `cargo` and `cargoQueue`, the "event"-style methods, like `q.drain` and `q.saturated` are now methods that register a callback, rather than properties you assign a callback to.  They are now of the form `q.drain(callback)`.  If you do not pass a callback a Promise will be returned for the next occurrence of the event, making them `await`-able, e.g. `await q.drain()`.  (#1586, #1641)
+- Calling `callback(false)` will cancel an async method, preventing further iteration and callback calls.  This is useful for preventing memory leaks when you break out of an async flow by calling an outer callback. (#1064, #1542)
+- `during` and `doDuring` have been removed, and instead `whilst`, `doWhilst`, `until` and `doUntil` now have asynchronous `test` functions. (#850, #1557)
+- `limits` of less than 1 now cause an error to be thrown in queues and collection methods. (#1249, #1552)
+- `memoize` no longer memoizes errors (#1465, #1466)
+- `applyEach`/`applyEachSeries` have a simpler interface, to make them more easily type-able.  It always returns a function that takes in a single callback argument.  If that callback is omitted, a promise is returned, making it awaitable. (#1228, #1640)
+
+## New Features
+- Async generators are now supported in all the Collection methods. (#1560)
+- Added `cargoQueue`, a queue with both `concurrency` and `payload` size parameters. (#1567)
+- Queue objects returned from `queue` now have a `Symbol.iterator` method, meaning they can be iterated over to inspect the current list of items in the queue. (#1459, #1556)
+- A ESM-flavored `async.mjs` is included in the `async` package.  This is described in the `package.json` `"module"` field, meaning it should be automatically used by Webpack and other compatible bundlers.
+
+## Bug fixes
+- Better handle arbitrary error objects in `asyncify` (#1568, #1569)
+
+## Other
+- Removed Lodash as a dependency (#1283, #1528)
+- Miscellaneous docs fixes (#1393, #1501, #1540, #1543, #1558, #1563, #1564, #1579, #1581)
+- Miscellaneous test fixes (#1538)
+
+-------
+
+# v2.6.1
+- Updated lodash to prevent `npm audit` warnings. (#1532, #1533)
+- Made `async-es` more optimized for webpack users (#1517)
+- Fixed a stack overflow with large collections and a synchronous iterator (#1514)
+- Various small fixes/chores (#1505, #1511, #1527, #1530)
+
+# v2.6.0
+- Added missing aliases for many methods.  Previously, you could not (e.g.) `require('async/find')` or use `async.anyLimit`. (#1483)
+- Improved `queue` performance. (#1448, #1454)
+- Add missing sourcemap (#1452, #1453)
+- Various doc updates (#1448, #1471, #1483)
+
+# v2.5.0
+- Added `concatLimit`, the `Limit` equivalent of [`concat`](https://caolan.github.io/async/docs.html#concat) ([#1426](https://github.com/caolan/async/issues/1426), [#1430](https://github.com/caolan/async/pull/1430))
+- `concat` improvements: it now preserves order, handles falsy values and the `iteratee` callback takes a variable number of arguments ([#1437](https://github.com/caolan/async/issues/1437), [#1436](https://github.com/caolan/async/pull/1436))
+- Fixed an issue in `queue`  where there was a size discrepancy between `workersList().length` and `running()` ([#1428](https://github.com/caolan/async/issues/1428), [#1429](https://github.com/caolan/async/pull/1429))
+- Various doc fixes ([#1422](https://github.com/caolan/async/issues/1422), [#1424](https://github.com/caolan/async/pull/1424))
+
+# v2.4.1
+- Fixed a bug preventing functions wrapped  with `timeout()` from being re-used. ([#1418](https://github.com/caolan/async/issues/1418), [#1419](https://github.com/caolan/async/issues/1419))
+
+# v2.4.0
+- Added `tryEach`, for running async functions in parallel, where you only expect one to succeed. ([#1365](https://github.com/caolan/async/issues/1365), [#687](https://github.com/caolan/async/issues/687))
+- Improved performance, most notably in `parallel` and `waterfall` ([#1395](https://github.com/caolan/async/issues/1395))
+- Added `queue.remove()`, for removing items in a `queue` ([#1397](https://github.com/caolan/async/issues/1397), [#1391](https://github.com/caolan/async/issues/1391))
+- Fixed using `eval`, preventing Async from running in pages with Content Security Policy ([#1404](https://github.com/caolan/async/issues/1404), [#1403](https://github.com/caolan/async/issues/1403))
+- Fixed errors thrown in an `asyncify`ed function's callback being caught by the underlying Promise ([#1408](https://github.com/caolan/async/issues/1408))
+- Fixed timing of `queue.empty()` ([#1367](https://github.com/caolan/async/issues/1367))
+- Various doc fixes ([#1314](https://github.com/caolan/async/issues/1314), [#1394](https://github.com/caolan/async/issues/1394), [#1412](https://github.com/caolan/async/issues/1412))
+
+# v2.3.0
+- Added support for ES2017 `async` functions.  Wherever you can pass a Node-style/CPS function that uses a callback, you can also pass an `async` function.  Previously, you had to wrap `async` functions with `asyncify`.  The caveat is that it will only work if `async` functions are supported natively in your environment, transpiled implementations can't be detected.  ([#1386](https://github.com/caolan/async/issues/1386), [#1390](https://github.com/caolan/async/issues/1390))
+- Small doc fix ([#1392](https://github.com/caolan/async/issues/1392))
+
+# v2.2.0
+- Added `groupBy`, and the `Series`/`Limit` equivalents, analogous to [`_.groupBy`](http://lodash.com/docs#groupBy) ([#1364](https://github.com/caolan/async/issues/1364))
+- Fixed `transform` bug when `callback` was not passed ([#1381](https://github.com/caolan/async/issues/1381))
+- Added note about `reflect` to `parallel` docs ([#1385](https://github.com/caolan/async/issues/1385))
+
+# v2.1.5
+- Fix `auto` bug when function names collided with Array.prototype ([#1358](https://github.com/caolan/async/issues/1358))
+- Improve some error messages ([#1349](https://github.com/caolan/async/issues/1349))
+- Avoid stack overflow case in queue
+- Fixed an issue in `some`, `every` and `find` where processing would continue after the result was determined.
+- Cleanup implementations of `some`, `every` and `find`
+
+# v2.1.3
+- Make bundle size smaller
+- Create optimized hotpath for `filter` in array case.
+
+# v2.1.2
+- Fixed a stackoverflow bug with `detect`, `some`, `every` on large inputs ([#1293](https://github.com/caolan/async/issues/1293)).
+
+# v2.1.0
+
+- `retry` and `retryable` now support an optional `errorFilter` function that determines if the `task` should retry on the error ([#1256](https://github.com/caolan/async/issues/1256), [#1261](https://github.com/caolan/async/issues/1261))
+- Optimized array iteration in `race`, `cargo`, `queue`, and `priorityQueue` ([#1253](https://github.com/caolan/async/issues/1253))
+- Added alias documentation to doc site ([#1251](https://github.com/caolan/async/issues/1251), [#1254](https://github.com/caolan/async/issues/1254))
+- Added [BootStrap scrollspy](http://getbootstrap.com/javascript/#scrollspy) to docs to highlight in the sidebar the current method being viewed  ([#1289](https://github.com/caolan/async/issues/1289), [#1300](https://github.com/caolan/async/issues/1300))
+- Various minor doc fixes ([#1263](https://github.com/caolan/async/issues/1263), [#1264](https://github.com/caolan/async/issues/1264), [#1271](https://github.com/caolan/async/issues/1271), [#1278](https://github.com/caolan/async/issues/1278), [#1280](https://github.com/caolan/async/issues/1280), [#1282](https://github.com/caolan/async/issues/1282), [#1302](https://github.com/caolan/async/issues/1302))
+
+# v2.0.1
+
+- Significantly optimized all iteration based collection methods such as `each`, `map`, `filter`, etc ([#1245](https://github.com/caolan/async/issues/1245), [#1246](https://github.com/caolan/async/issues/1246), [#1247](https://github.com/caolan/async/issues/1247)).
+
+# v2.0.0
+
+Lots of changes here!
+
+First and foremost, we have a slick new [site for docs](https://caolan.github.io/async/). Special thanks to [**@hargasinski**](https://github.com/hargasinski) for his work converting our old docs to `jsdoc` format and implementing the new website. Also huge ups to [**@ivanseidel**](https://github.com/ivanseidel) for designing our new logo. It was a long process for both of these tasks, but I think these changes turned out extraordinary well.
+
+The biggest feature is modularization. You can now `require("async/series")` to only require the `series` function. Every Async library function is available this way. You still can `require("async")` to require the entire library, like you could do before.
+
+We also provide Async as a collection of ES2015 modules. You can now `import {each} from 'async-es'` or `import waterfall from 'async-es/waterfall'`. If you are using only a few Async functions, and are using a ES bundler such as Rollup, this can significantly lower your build size.
+
+Major thanks to [**@Kikobeats**](github.com/Kikobeats), [**@aearly**](github.com/aearly) and [**@megawac**](github.com/megawac) for doing the majority of the modularization work, as well as [**@jdalton**](github.com/jdalton) and [**@Rich-Harris**](github.com/Rich-Harris) for advisory work on the general modularization strategy.
+
+Another one of the general themes of the 2.0 release is standardization of what an "async" function is. We are now more strictly following the node-style continuation passing style. That is, an async function is a function that:
+
+1. Takes a variable number of arguments
+2. The last argument is always a callback
+3. The callback can accept any number of arguments
+4. The first argument passed to the callback will be treated as an error result, if the argument is truthy
+5. Any number of result arguments can be passed after the "error" argument
+6. The callback is called once and exactly once, either on the same tick or later tick of the JavaScript event loop.
+
+There were several cases where Async accepted some functions that did not strictly have these properties, most notably `auto`, `every`, `some`, `filter`, `reject` and `detect`.
+
+Another theme is performance. We have eliminated internal deferrals in all cases where they make sense. For example, in `waterfall` and `auto`, there was a `setImmediate` between each task -- these deferrals have been removed. A `setImmediate` call can add up to 1ms of delay. This might not seem like a lot, but it can add up if you are using many Async functions in the course of processing a HTTP request, for example. Nearly all asynchronous functions that do I/O already have some sort of deferral built in, so the extra deferral is unnecessary. The trade-off of this change is removing our built-in stack-overflow defense. Many synchronous callback calls in series can quickly overflow the JS call stack. If you do have a function that is sometimes synchronous (calling its callback on the same tick), and are running into stack overflows, wrap it with `async.ensureAsync()`.
+
+Another big performance win has been re-implementing `queue`, `cargo`, and `priorityQueue` with [doubly linked lists](https://en.wikipedia.org/wiki/Doubly_linked_list) instead of arrays. This has lead to queues being an order of [magnitude faster on large sets of tasks](https://github.com/caolan/async/pull/1205).
+
+## New Features
+
+- Async is now modularized. Individual functions can be `require()`d from the main package. (`require('async/auto')`) ([#984](https://github.com/caolan/async/issues/984), [#996](https://github.com/caolan/async/issues/996))
+- Async is also available as a collection of ES2015 modules in the new `async-es` package. (`import {forEachSeries} from 'async-es'`) ([#984](https://github.com/caolan/async/issues/984), [#996](https://github.com/caolan/async/issues/996))
+- Added `race`, analogous to `Promise.race()`. It will run an array of async tasks in parallel and will call its callback with the result of the first task to respond. ([#568](https://github.com/caolan/async/issues/568), [#1038](https://github.com/caolan/async/issues/1038))
+- Collection methods now accept ES2015 iterators.  Maps, Sets, and anything that implements the iterator spec can now be passed directly to `each`, `map`, `parallel`, etc.. ([#579](https://github.com/caolan/async/issues/579), [#839](https://github.com/caolan/async/issues/839), [#1074](https://github.com/caolan/async/issues/1074))
+- Added `mapValues`, for mapping over the properties of an object and returning an object with the same keys. ([#1157](https://github.com/caolan/async/issues/1157), [#1177](https://github.com/caolan/async/issues/1177))
+- Added `timeout`, a wrapper for an async function that will make the task time-out after the specified time. ([#1007](https://github.com/caolan/async/issues/1007), [#1027](https://github.com/caolan/async/issues/1027))
+- Added `reflect` and `reflectAll`, analagous to [`Promise.reflect()`](http://bluebirdjs.com/docs/api/reflect.html), a wrapper for async tasks that always succeeds, by gathering results and errors into an object.  ([#942](https://github.com/caolan/async/issues/942), [#1012](https://github.com/caolan/async/issues/1012), [#1095](https://github.com/caolan/async/issues/1095))
+- `constant` supports dynamic arguments -- it will now always use its last argument as the callback. ([#1016](https://github.com/caolan/async/issues/1016), [#1052](https://github.com/caolan/async/issues/1052))
+- `setImmediate` and `nextTick` now support arguments to partially apply to the deferred function, like the node-native versions do. ([#940](https://github.com/caolan/async/issues/940), [#1053](https://github.com/caolan/async/issues/1053))
+- `auto` now supports resolving cyclic dependencies using [Kahn's algorithm](https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm) ([#1140](https://github.com/caolan/async/issues/1140)).
+- Added `autoInject`, a relative of `auto` that automatically spreads a task's dependencies as arguments to the task function. ([#608](https://github.com/caolan/async/issues/608), [#1055](https://github.com/caolan/async/issues/1055), [#1099](https://github.com/caolan/async/issues/1099), [#1100](https://github.com/caolan/async/issues/1100))
+- You can now limit the concurrency of `auto` tasks. ([#635](https://github.com/caolan/async/issues/635), [#637](https://github.com/caolan/async/issues/637))
+- Added `retryable`, a relative of `retry` that wraps an async function, making it retry when called. ([#1058](https://github.com/caolan/async/issues/1058))
+- `retry` now supports specifying a function that determines the next time interval, useful for exponential backoff, logging and other retry strategies. ([#1161](https://github.com/caolan/async/issues/1161))
+- `retry` will now pass all of the arguments the task function was resolved with to the callback ([#1231](https://github.com/caolan/async/issues/1231)).
+- Added `q.unsaturated` -- callback called when a `queue`'s number of running workers falls below a threshold. ([#868](https://github.com/caolan/async/issues/868), [#1030](https://github.com/caolan/async/issues/1030), [#1033](https://github.com/caolan/async/issues/1033), [#1034](https://github.com/caolan/async/issues/1034))
+- Added `q.error` -- a callback called whenever a `queue` task calls its callback with an error. ([#1170](https://github.com/caolan/async/issues/1170))
+- `applyEach` and `applyEachSeries` now pass results to the final callback. ([#1088](https://github.com/caolan/async/issues/1088))
+
+## Breaking changes
+
+- Calling a callback more than once is considered an error, and an error will be thrown. This had an explicit breaking change in `waterfall`. If you were relying on this behavior, you should more accurately represent your control flow as an event emitter or stream. ([#814](https://github.com/caolan/async/issues/814), [#815](https://github.com/caolan/async/issues/815), [#1048](https://github.com/caolan/async/issues/1048), [#1050](https://github.com/caolan/async/issues/1050))
+- `auto` task functions now always take the callback as the last argument. If a task has dependencies, the `results` object will be passed as the first argument. To migrate old task functions, wrap them with [`_.flip`](https://lodash.com/docs#flip) ([#1036](https://github.com/caolan/async/issues/1036), [#1042](https://github.com/caolan/async/issues/1042))
+- Internal `setImmediate` calls have been refactored away. This may make existing flows vulnerable to stack overflows if you use many synchronous functions in series. Use `ensureAsync` to work around this. ([#696](https://github.com/caolan/async/issues/696), [#704](https://github.com/caolan/async/issues/704), [#1049](https://github.com/caolan/async/issues/1049), [#1050](https://github.com/caolan/async/issues/1050))
+- `map` used to return an object when iterating over an object.  `map` now always returns an array, like in other libraries.  The previous object behavior has been split out into `mapValues`. ([#1157](https://github.com/caolan/async/issues/1157), [#1177](https://github.com/caolan/async/issues/1177))
+- `filter`, `reject`, `some`, `every`, `detect` and their families like `{METHOD}Series` and `{METHOD}Limit` now expect an error as the first callback argument, rather than just a simple boolean. Pass `null` as the first argument, or use `fs.access` instead of `fs.exists`. ([#118](https://github.com/caolan/async/issues/118), [#774](https://github.com/caolan/async/issues/774), [#1028](https://github.com/caolan/async/issues/1028), [#1041](https://github.com/caolan/async/issues/1041))
+- `{METHOD}` and `{METHOD}Series` are now implemented in terms of `{METHOD}Limit`. This is a major internal simplification, and is not expected to cause many problems, but it does subtly affect how functions execute internally. ([#778](https://github.com/caolan/async/issues/778), [#847](https://github.com/caolan/async/issues/847))
+- `retry`'s callback is now optional. Previously, omitting the callback would partially apply the function, meaning it could be passed directly as a task to `series` or `auto`. The partially applied "control-flow" behavior has been separated out into `retryable`. ([#1054](https://github.com/caolan/async/issues/1054), [#1058](https://github.com/caolan/async/issues/1058))
+- The test function for `whilst`, `until`, and `during` used to be passed non-error args from the iteratee function's callback, but this led to weirdness where the first call of the test function would be passed no args. We have made it so the test function is never passed extra arguments, and only the `doWhilst`, `doUntil`, and `doDuring` functions pass iteratee callback arguments to the test function ([#1217](https://github.com/caolan/async/issues/1217), [#1224](https://github.com/caolan/async/issues/1224))
+- The `q.tasks` array has been renamed `q._tasks` and is now implemented as a doubly linked list (DLL). Any code that used to interact with this array will need to be updated to either use the provided helpers or support DLLs ([#1205](https://github.com/caolan/async/issues/1205)).
+- The timing of the `q.saturated()` callback in a `queue` has been modified to better reflect when tasks pushed to the queue will start queueing. ([#724](https://github.com/caolan/async/issues/724), [#1078](https://github.com/caolan/async/issues/1078))
+- Removed `iterator` method in favour of [ES2015 iterator protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators ) which natively supports arrays ([#1237](https://github.com/caolan/async/issues/1237))
+- Dropped support for Component, Jam, SPM, and Volo ([#1175](https://github.com/caolan/async/issues/1175), #[#176](https://github.com/caolan/async/issues/176))
+
+## Bug Fixes
+
+- Improved handling of no dependency cases in `auto` & `autoInject` ([#1147](https://github.com/caolan/async/issues/1147)).
+- Fixed a bug where the callback generated by `asyncify` with  `Promises` could resolve twice ([#1197](https://github.com/caolan/async/issues/1197)).
+- Fixed several documented optional callbacks not actually being optional ([#1223](https://github.com/caolan/async/issues/1223)).
+
+## Other
+
+- Added `someSeries` and `everySeries` for symmetry, as well as a complete set of `any`/`anyLimit`/`anySeries` and `all`/`/allLmit`/`allSeries` aliases.
+- Added `find` as an alias for `detect. (as well as `findLimit` and `findSeries`).
+- Various doc fixes ([#1005](https://github.com/caolan/async/issues/1005), [#1008](https://github.com/caolan/async/issues/1008), [#1010](https://github.com/caolan/async/issues/1010), [#1015](https://github.com/caolan/async/issues/1015), [#1021](https://github.com/caolan/async/issues/1021), [#1037](https://github.com/caolan/async/issues/1037), [#1039](https://github.com/caolan/async/issues/1039), [#1051](https://github.com/caolan/async/issues/1051), [#1102](https://github.com/caolan/async/issues/1102), [#1107](https://github.com/caolan/async/issues/1107), [#1121](https://github.com/caolan/async/issues/1121), [#1123](https://github.com/caolan/async/issues/1123), [#1129](https://github.com/caolan/async/issues/1129), [#1135](https://github.com/caolan/async/issues/1135), [#1138](https://github.com/caolan/async/issues/1138), [#1141](https://github.com/caolan/async/issues/1141), [#1153](https://github.com/caolan/async/issues/1153), [#1216](https://github.com/caolan/async/issues/1216), [#1217](https://github.com/caolan/async/issues/1217), [#1232](https://github.com/caolan/async/issues/1232), [#1233](https://github.com/caolan/async/issues/1233), [#1236](https://github.com/caolan/async/issues/1236), [#1238](https://github.com/caolan/async/issues/1238))
+
+Thank you [**@aearly**](github.com/aearly) and [**@megawac**](github.com/megawac) for taking the lead on version 2 of async.
+
+------------------------------------------
+
+# v1.5.2
+- Allow using `"constructor"` as an argument in `memoize` ([#998](https://github.com/caolan/async/issues/998))
+- Give a better error messsage when `auto` dependency checking fails ([#994](https://github.com/caolan/async/issues/994))
+- Various doc updates ([#936](https://github.com/caolan/async/issues/936), [#956](https://github.com/caolan/async/issues/956), [#979](https://github.com/caolan/async/issues/979), [#1002](https://github.com/caolan/async/issues/1002))
+
+# v1.5.1
+- Fix issue with `pause` in `queue` with concurrency enabled ([#946](https://github.com/caolan/async/issues/946))
+- `while` and `until` now pass the final result to callback ([#963](https://github.com/caolan/async/issues/963))
+- `auto` will properly handle concurrency when there is no callback ([#966](https://github.com/caolan/async/issues/966))
+- `auto` will no. properly stop execution when an error occurs ([#988](https://github.com/caolan/async/issues/988), [#993](https://github.com/caolan/async/issues/993))
+- Various doc fixes ([#971](https://github.com/caolan/async/issues/971), [#980](https://github.com/caolan/async/issues/980))
+
+# v1.5.0
+
+- Added `transform`, analogous to [`_.transform`](http://lodash.com/docs#transform) ([#892](https://github.com/caolan/async/issues/892))
+- `map` now returns an object when an object is passed in, rather than array with non-numeric keys. `map` will begin always returning an array with numeric indexes in the next major release. ([#873](https://github.com/caolan/async/issues/873))
+- `auto` now accepts an optional `concurrency` argument to limit the number o. running tasks ([#637](https://github.com/caolan/async/issues/637))
+- Added `queue#workersList()`, to retrieve the lis. of currently running tasks. ([#891](https://github.com/caolan/async/issues/891))
+- Various code simplifications ([#896](https://github.com/caolan/async/issues/896), [#904](https://github.com/caolan/async/issues/904))
+- Various doc fixes :scroll: ([#890](https://github.com/caolan/async/issues/890), [#894](https://github.com/caolan/async/issues/894), [#903](https://github.com/caolan/async/issues/903), [#905](https://github.com/caolan/async/issues/905), [#912](https://github.com/caolan/async/issues/912))
+
+# v1.4.2
+
+- Ensure coverage files don't get published on npm ([#879](https://github.com/caolan/async/issues/879))
+
+# v1.4.1
+
+- Add in overlooked `detectLimit` method ([#866](https://github.com/caolan/async/issues/866))
+- Removed unnecessary files from npm releases ([#861](https://github.com/caolan/async/issues/861))
+- Removed usage of a reserved word to prevent :boom: in older environments ([#870](https://github.com/caolan/async/issues/870))
+
+# v1.4.0
+
+- `asyncify` now supports promises ([#840](https://github.com/caolan/async/issues/840))
+- Added `Limit` versions of `filter` and `reject` ([#836](https://github.com/caolan/async/issues/836))
+- Add `Limit` versions of `detect`, `some` and `every` ([#828](https://github.com/caolan/async/issues/828), [#829](https://github.com/caolan/async/issues/829))
+- `some`, `every` and `detect` now short circuit early ([#828](https://github.com/caolan/async/issues/828), [#829](https://github.com/caolan/async/issues/829))
+- Improve detection of the global object ([#804](https://github.com/caolan/async/issues/804)), enabling use in WebWorkers
+- `whilst` now called with arguments from iterator ([#823](https://github.com/caolan/async/issues/823))
+- `during` now gets called with arguments from iterator ([#824](https://github.com/caolan/async/issues/824))
+- Code simplifications and optimizations aplenty ([diff](https://github.com/caolan/async/compare/v1.3.0...v1.4.0))
+
+
+# v1.3.0
+
+New Features:
+- Added `constant`
+- Added `asyncify`/`wrapSync` for making sync functions work with callbacks. ([#671](https://github.com/caolan/async/issues/671), [#806](https://github.com/caolan/async/issues/806))
+- Added `during` and `doDuring`, which are like `whilst` with an async truth test. ([#800](https://github.com/caolan/async/issues/800))
+- `retry` now accepts an `interval` parameter to specify a delay between retries. ([#793](https://github.com/caolan/async/issues/793))
+- `async` should work better in Web Workers due to better `root` detection ([#804](https://github.com/caolan/async/issues/804))
+- Callbacks are now optional in `whilst`, `doWhilst`, `until`, and `doUntil` ([#642](https://github.com/caolan/async/issues/642))
+- Various internal updates ([#786](https://github.com/caolan/async/issues/786), [#801](https://github.com/caolan/async/issues/801), [#802](https://github.com/caolan/async/issues/802), [#803](https://github.com/caolan/async/issues/803))
+- Various doc fixes ([#790](https://github.com/caolan/async/issues/790), [#794](https://github.com/caolan/async/issues/794))
+
+Bug Fixes:
+- `cargo` now exposes the `payload` size, and `cargo.payload` can be changed on the fly after the `cargo` is created. ([#740](https://github.com/caolan/async/issues/740), [#744](https://github.com/caolan/async/issues/744), [#783](https://github.com/caolan/async/issues/783))
+
+
+# v1.2.1
+
+Bug Fix:
+
+- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. ([#782](https://github.com/caolan/async/issues/782))
+
+
+# v1.2.0
+
+New Features:
+
+- Added `timesLimit` ([#743](https://github.com/caolan/async/issues/743))
+- `concurrency` can be changed after initialization in `queue` by setting `q.concurrency`. The new concurrency will be reflected the next time a task is processed. ([#747](https://github.com/caolan/async/issues/747), [#772](https://github.com/caolan/async/issues/772))
+
+Bug Fixes:
+
+- Fixed a regression in `each` and family with empty arrays that have additional properties. ([#775](https://github.com/caolan/async/issues/775), [#777](https://github.com/caolan/async/issues/777))
+
+
+# v1.1.1
+
+Bug Fix:
+
+- Small regression with synchronous iterator behavior in `eachSeries` with a 1-element array. Before 1.1.0, `eachSeries`'s callback was called on the same tick, which this patch restores. In 2.0.0, it will be called on the next tick. ([#782](https://github.com/caolan/async/issues/782))
+
+
+# v1.1.0
+
+New Features:
+
+- `cargo` now supports all of the same methods and event callbacks as `queue`.
+- Added `ensureAsync` - A wrapper that ensures an async function calls its callback on a later tick. ([#769](https://github.com/caolan/async/issues/769))
+- Optimized `map`, `eachOf`, and `waterfall` families of functions
+- Passing a `null` or `undefined` array to `map`, `each`, `parallel` and families will be treated as an empty array ([#667](https://github.com/caolan/async/issues/667)).
+- The callback is now optional for the composed results of `compose` and `seq`. ([#618](https://github.com/caolan/async/issues/618))
+- Reduced file size by 4kb, (minified version by 1kb)
+- Added code coverage through `nyc` and `coveralls` ([#768](https://github.com/caolan/async/issues/768))
+
+Bug Fixes:
+
+- `forever` will no longer stack overflow with a synchronous iterator ([#622](https://github.com/caolan/async/issues/622))
+- `eachLimit` and other limit functions will stop iterating once an error occurs ([#754](https://github.com/caolan/async/issues/754))
+- Always pass `null` in callbacks when there is no error ([#439](https://github.com/caolan/async/issues/439))
+- Ensure proper conditions when calling `drain()` after pushing an empty data set to a queue ([#668](https://github.com/caolan/async/issues/668))
+- `each` and family will properly handle an empty array ([#578](https://github.com/caolan/async/issues/578))
+- `eachSeries` and family will finish if the underlying array is modified during execution ([#557](https://github.com/caolan/async/issues/557))
+- `queue` will throw if a non-function is passed to `q.push()` ([#593](https://github.com/caolan/async/issues/593))
+- Doc fixes ([#629](https://github.com/caolan/async/issues/629), [#766](https://github.com/caolan/async/issues/766))
+
+
+# v1.0.0
+
+No known breaking changes, we are simply complying with semver from here on out.
+
+Changes:
+
+- Start using a changelog!
+- Add `forEachOf` for iterating over Objects (or to iterate Arrays with indexes available) ([#168](https://github.com/caolan/async/issues/168) [#704](https://github.com/caolan/async/issues/704) [#321](https://github.com/caolan/async/issues/321))
+- Detect deadlocks in `auto` ([#663](https://github.com/caolan/async/issues/663))
+- Better support for require.js ([#527](https://github.com/caolan/async/issues/527))
+- Throw if queue created with concurrency `0` ([#714](https://github.com/caolan/async/issues/714))
+- Fix unneeded iteration in `queue.resume()` ([#758](https://github.com/caolan/async/issues/758))
+- Guard against timer mocking overriding `setImmediate` ([#609](https://github.com/caolan/async/issues/609) [#611](https://github.com/caolan/async/issues/611))
+- Miscellaneous doc fixes ([#542](https://github.com/caolan/async/issues/542) [#596](https://github.com/caolan/async/issues/596) [#615](https://github.com/caolan/async/issues/615) [#628](https://github.com/caolan/async/issues/628) [#631](https://github.com/caolan/async/issues/631) [#690](https://github.com/caolan/async/issues/690) [#729](https://github.com/caolan/async/issues/729))
+- Use single noop function internally ([#546](https://github.com/caolan/async/issues/546))
+- Optimize internal `_each`, `_map` and `_keys` functions.
diff --git a/node_modules/async/LICENSE b/node_modules/async/LICENSE
index 8f29698588533b535c9989361c44abacf23512ae..b18aed69219562718858d972467ba0a68b1ce178 100644
--- a/node_modules/async/LICENSE
+++ b/node_modules/async/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2010-2014 Caolan McMahon
+Copyright (c) 2010-2018 Caolan McMahon
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/node_modules/async/README.md b/node_modules/async/README.md
index 6cfb922c53f683fc12aa45d251c77d72960c8c2c..77f645e2fb8936a6efdfab4711b99e7a8ee9ecb0 100644
--- a/node_modules/async/README.md
+++ b/node_modules/async/README.md
@@ -1,1647 +1,59 @@
-# Async.js
+![Async Logo](https://raw.githubusercontent.com/caolan/async/master/logo/async-logo_readme.jpg)
 
-[![Build Status via Travis CI](https://travis-ci.org/caolan/async.svg?branch=master)](https://travis-ci.org/caolan/async)
+![Github Actions CI status](https://github.com/caolan/async/actions/workflows/ci.yml/badge.svg)
+[![NPM version](https://img.shields.io/npm/v/async.svg)](https://www.npmjs.com/package/async)
+[![Coverage Status](https://coveralls.io/repos/caolan/async/badge.svg?branch=master)](https://coveralls.io/r/caolan/async?branch=master)
+[![Join the chat at https://gitter.im/caolan/async](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/caolan/async?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![jsDelivr Hits](https://data.jsdelivr.com/v1/package/npm/async/badge?style=rounded)](https://www.jsdelivr.com/package/npm/async)
 
+<!--
+|Linux|Windows|MacOS|
+|-|-|-|
+|[![Linux Build Status](https://dev.azure.com/caolanmcmahon/async/_apis/build/status/caolan.async?branchName=master&jobName=Linux&configuration=Linux%20node_10_x)](https://dev.azure.com/caolanmcmahon/async/_build/latest?definitionId=1&branchName=master) | [![Windows Build Status](https://dev.azure.com/caolanmcmahon/async/_apis/build/status/caolan.async?branchName=master&jobName=Windows&configuration=Windows%20node_10_x)](https://dev.azure.com/caolanmcmahon/async/_build/latest?definitionId=1&branchName=master) | [![MacOS Build Status](https://dev.azure.com/caolanmcmahon/async/_apis/build/status/caolan.async?branchName=master&jobName=OSX&configuration=OSX%20node_10_x)](https://dev.azure.com/caolanmcmahon/async/_build/latest?definitionId=1&branchName=master)| -->
 
-Async is a utility module which provides straight-forward, powerful functions
-for working with asynchronous JavaScript. Although originally designed for
-use with [Node.js](http://nodejs.org) and installable via `npm install async`,
-it can also be used directly in the browser.
+Async is a utility module which provides straight-forward, powerful functions for working with [asynchronous JavaScript](http://caolan.github.io/async/v3/global.html). Although originally designed for use with [Node.js](https://nodejs.org/) and installable via `npm i async`, it can also be used directly in the browser.  A ESM/MJS version is included in the main `async` package that should automatically be used with compatible bundlers such as Webpack and Rollup.
 
-Async is also installable via:
+A pure ESM version of Async is available as [`async-es`](https://www.npmjs.com/package/async-es).
 
-- [bower](http://bower.io/): `bower install async`
-- [component](https://github.com/component/component): `component install
-  caolan/async`
-- [jam](http://jamjs.org/): `jam install async`
-- [spm](http://spmjs.io/): `spm install async`
+For Documentation, visit <https://caolan.github.io/async/>
 
-Async provides around 20 functions that include the usual 'functional'
-suspects (`map`, `reduce`, `filter`, `each`…) as well as some common patterns
-for asynchronous control flow (`parallel`, `series`, `waterfall`…). All these
-functions assume you follow the Node.js convention of providing a single
-callback as the last argument of your `async` function.
+*For Async v1.5.x documentation, go [HERE](https://github.com/caolan/async/blob/v1.5.2/README.md)*
 
 
-## Quick Examples
-
 ```javascript
-async.map(['file1','file2','file3'], fs.stat, function(err, results){
-    // results is now an array of stats for each file
-});
-
-async.filter(['file1','file2','file3'], fs.exists, function(results){
-    // results now equals an array of the existing files
-});
-
-async.parallel([
-    function(){ ... },
-    function(){ ... }
-], callback);
-
-async.series([
-    function(){ ... },
-    function(){ ... }
-]);
-```
-
-There are many more functions available so take a look at the docs below for a
-full list. This module aims to be comprehensive, so if you feel anything is
-missing please create a GitHub issue for it.
-
-## Common Pitfalls
-
-### Binding a context to an iterator
-
-This section is really about `bind`, not about `async`. If you are wondering how to
-make `async` execute your iterators in a given context, or are confused as to why
-a method of another library isn't working as an iterator, study this example:
-
-```js
-// Here is a simple object with an (unnecessarily roundabout) squaring method
-var AsyncSquaringLibrary = {
-  squareExponent: 2,
-  square: function(number, callback){ 
-    var result = Math.pow(number, this.squareExponent);
-    setTimeout(function(){
-      callback(null, result);
-    }, 200);
-  }
-};
-
-async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){
-  // result is [NaN, NaN, NaN]
-  // This fails because the `this.squareExponent` expression in the square
-  // function is not evaluated in the context of AsyncSquaringLibrary, and is
-  // therefore undefined.
-});
-
-async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){
-  // result is [1, 4, 9]
-  // With the help of bind we can attach a context to the iterator before
-  // passing it to async. Now the square function will be executed in its 
-  // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent`
-  // will be as expected.
-});
-```
-
-## Download
-
-The source is available for download from
-[GitHub](http://github.com/caolan/async).
-Alternatively, you can install using Node Package Manager (`npm`):
-
-    npm install async
-
-__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed
-
-## In the Browser
-
-So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. 
-
-Usage:
-
-```html
-<script type="text/javascript" src="async.js"></script>
-<script type="text/javascript">
-
-    async.map(data, asyncProcess, function(err, results){
-        alert(results);
-    });
-
-</script>
-```
-
-## Documentation
-
-### Collections
-
-* [`each`](#each)
-* [`eachSeries`](#eachSeries)
-* [`eachLimit`](#eachLimit)
-* [`map`](#map)
-* [`mapSeries`](#mapSeries)
-* [`mapLimit`](#mapLimit)
-* [`filter`](#filter)
-* [`filterSeries`](#filterSeries)
-* [`reject`](#reject)
-* [`rejectSeries`](#rejectSeries)
-* [`reduce`](#reduce)
-* [`reduceRight`](#reduceRight)
-* [`detect`](#detect)
-* [`detectSeries`](#detectSeries)
-* [`sortBy`](#sortBy)
-* [`some`](#some)
-* [`every`](#every)
-* [`concat`](#concat)
-* [`concatSeries`](#concatSeries)
-
-### Control Flow
-
-* [`series`](#seriestasks-callback)
-* [`parallel`](#parallel)
-* [`parallelLimit`](#parallellimittasks-limit-callback)
-* [`whilst`](#whilst)
-* [`doWhilst`](#doWhilst)
-* [`until`](#until)
-* [`doUntil`](#doUntil)
-* [`forever`](#forever)
-* [`waterfall`](#waterfall)
-* [`compose`](#compose)
-* [`seq`](#seq)
-* [`applyEach`](#applyEach)
-* [`applyEachSeries`](#applyEachSeries)
-* [`queue`](#queue)
-* [`priorityQueue`](#priorityQueue)
-* [`cargo`](#cargo)
-* [`auto`](#auto)
-* [`retry`](#retry)
-* [`iterator`](#iterator)
-* [`apply`](#apply)
-* [`nextTick`](#nextTick)
-* [`times`](#times)
-* [`timesSeries`](#timesSeries)
-
-### Utils
-
-* [`memoize`](#memoize)
-* [`unmemoize`](#unmemoize)
-* [`log`](#log)
-* [`dir`](#dir)
-* [`noConflict`](#noConflict)
-
-
-## Collections
-
-<a name="forEach" />
-<a name="each" />
-### each(arr, iterator, callback)
-
-Applies the function `iterator` to each item in `arr`, in parallel.
-The `iterator` is called with an item from the list, and a callback for when it
-has finished. If the `iterator` passes an error to its `callback`, the main
-`callback` (for the `each` function) is immediately called with the error.
-
-Note, that since this function applies `iterator` to each item in parallel,
-there is no guarantee that the iterator functions will complete in order.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  The iterator is passed a `callback(err)` which must be called once it has 
-  completed. If no error has occurred, the `callback` should be run without 
-  arguments or with an explicit `null` argument.
-* `callback(err)` - A callback which is called when all `iterator` functions
-  have finished, or an error occurs.
-
-__Examples__
-
-
-```js
-// assuming openFiles is an array of file names and saveFile is a function
-// to save the modified contents of that file:
-
-async.each(openFiles, saveFile, function(err){
-    // if any of the saves produced an error, err would equal that error
-});
-```
-
-```js
-// assuming openFiles is an array of file names 
-
-async.each(openFiles, function(file, callback) {
-  
-  // Perform operation on file here.
-  console.log('Processing file ' + file);
-  
-  if( file.length > 32 ) {
-    console.log('This file name is too long');
-    callback('File name too long');
-  } else {
-    // Do work to process file here
-    console.log('File processed');
-    callback();
-  }
-}, function(err){
-    // if any of the file processing produced an error, err would equal that error
-    if( err ) {
-      // One of the iterations produced an error.
-      // All processing will now stop.
-      console.log('A file failed to process');
-    } else {
-      console.log('All files have been processed successfully');
-    }
-});
-```
-
----------------------------------------
-
-<a name="forEachSeries" />
-<a name="eachSeries" />
-### eachSeries(arr, iterator, callback)
-
-The same as [`each`](#each), only `iterator` is applied to each item in `arr` in
-series. The next `iterator` is only called once the current one has completed. 
-This means the `iterator` functions will complete in order.
-
-
----------------------------------------
-
-<a name="forEachLimit" />
-<a name="eachLimit" />
-### eachLimit(arr, limit, iterator, callback)
-
-The same as [`each`](#each), only no more than `limit` `iterator`s will be simultaneously 
-running at any time.
-
-Note that the items in `arr` are not processed in batches, so there is no guarantee that 
-the first `limit` `iterator` functions will complete before any others are started.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `limit` - The maximum number of `iterator`s to run at any time.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  The iterator is passed a `callback(err)` which must be called once it has 
-  completed. If no error has occurred, the callback should be run without 
-  arguments or with an explicit `null` argument.
-* `callback(err)` - A callback which is called when all `iterator` functions
-  have finished, or an error occurs.
-
-__Example__
-
-```js
-// Assume documents is an array of JSON objects and requestApi is a
-// function that interacts with a rate-limited REST api.
-
-async.eachLimit(documents, 20, requestApi, function(err){
-    // if any of the saves produced an error, err would equal that error
-});
-```
-
----------------------------------------
-
-<a name="map" />
-### map(arr, iterator, callback)
-
-Produces a new array of values by mapping each value in `arr` through
-the `iterator` function. The `iterator` is called with an item from `arr` and a
-callback for when it has finished processing. Each of these callback takes 2 arguments: 
-an `error`, and the transformed item from `arr`. If `iterator` passes an error to his 
-callback, the main `callback` (for the `map` function) is immediately called with the error.
-
-Note, that since this function applies the `iterator` to each item in parallel,
-there is no guarantee that the `iterator` functions will complete in order. 
-However, the results array will be in the same order as the original `arr`.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  The iterator is passed a `callback(err, transformed)` which must be called once 
-  it has completed with an error (which can be `null`) and a transformed item.
-* `callback(err, results)` - A callback which is called when all `iterator`
-  functions have finished, or an error occurs. Results is an array of the
-  transformed items from the `arr`.
-
-__Example__
-
-```js
-async.map(['file1','file2','file3'], fs.stat, function(err, results){
-    // results is now an array of stats for each file
-});
-```
-
----------------------------------------
-
-<a name="mapSeries" />
-### mapSeries(arr, iterator, callback)
-
-The same as [`map`](#map), only the `iterator` is applied to each item in `arr` in
-series. The next `iterator` is only called once the current one has completed. 
-The results array will be in the same order as the original.
-
-
----------------------------------------
-
-<a name="mapLimit" />
-### mapLimit(arr, limit, iterator, callback)
-
-The same as [`map`](#map), only no more than `limit` `iterator`s will be simultaneously 
-running at any time.
-
-Note that the items are not processed in batches, so there is no guarantee that 
-the first `limit` `iterator` functions will complete before any others are started.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `limit` - The maximum number of `iterator`s to run at any time.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  The iterator is passed a `callback(err, transformed)` which must be called once 
-  it has completed with an error (which can be `null`) and a transformed item.
-* `callback(err, results)` - A callback which is called when all `iterator`
-  calls have finished, or an error occurs. The result is an array of the
-  transformed items from the original `arr`.
-
-__Example__
-
-```js
-async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){
-    // results is now an array of stats for each file
-});
-```
-
----------------------------------------
-
-<a name="select" />
-<a name="filter" />
-### filter(arr, iterator, callback)
-
-__Alias:__ `select`
-
-Returns a new array of all the values in `arr` which pass an async truth test.
-_The callback for each `iterator` call only accepts a single argument of `true` or
-`false`; it does not accept an error argument first!_ This is in-line with the
-way node libraries work with truth tests like `fs.exists`. This operation is
-performed in parallel, but the results array will be in the same order as the
-original.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A truth test to apply to each item in `arr`.
-  The `iterator` is passed a `callback(truthValue)`, which must be called with a 
-  boolean argument once it has completed.
-* `callback(results)` - A callback which is called after all the `iterator`
-  functions have finished.
-
-__Example__
-
-```js
-async.filter(['file1','file2','file3'], fs.exists, function(results){
-    // results now equals an array of the existing files
-});
-```
-
----------------------------------------
-
-<a name="selectSeries" />
-<a name="filterSeries" />
-### filterSeries(arr, iterator, callback)
-
-__Alias:__ `selectSeries`
-
-The same as [`filter`](#filter) only the `iterator` is applied to each item in `arr` in
-series. The next `iterator` is only called once the current one has completed. 
-The results array will be in the same order as the original.
-
----------------------------------------
-
-<a name="reject" />
-### reject(arr, iterator, callback)
-
-The opposite of [`filter`](#filter). Removes values that pass an `async` truth test.
-
----------------------------------------
-
-<a name="rejectSeries" />
-### rejectSeries(arr, iterator, callback)
-
-The same as [`reject`](#reject), only the `iterator` is applied to each item in `arr`
-in series.
-
-
----------------------------------------
-
-<a name="reduce" />
-### reduce(arr, memo, iterator, callback)
-
-__Aliases:__ `inject`, `foldl`
-
-Reduces `arr` into a single value using an async `iterator` to return
-each successive step. `memo` is the initial state of the reduction. 
-This function only operates in series. 
-
-For performance reasons, it may make sense to split a call to this function into 
-a parallel map, and then use the normal `Array.prototype.reduce` on the results. 
-This function is for situations where each step in the reduction needs to be async; 
-if you can get the data before reducing it, then it's probably a good idea to do so.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `memo` - The initial state of the reduction.
-* `iterator(memo, item, callback)` - A function applied to each item in the
-  array to produce the next step in the reduction. The `iterator` is passed a
-  `callback(err, reduction)` which accepts an optional error as its first 
-  argument, and the state of the reduction as the second. If an error is 
-  passed to the callback, the reduction is stopped and the main `callback` is 
-  immediately called with the error.
-* `callback(err, result)` - A callback which is called after all the `iterator`
-  functions have finished. Result is the reduced value.
-
-__Example__
-
-```js
-async.reduce([1,2,3], 0, function(memo, item, callback){
-    // pointless async:
-    process.nextTick(function(){
-        callback(null, memo + item)
-    });
-}, function(err, result){
-    // result is now equal to the last value of memo, which is 6
-});
-```
-
----------------------------------------
-
-<a name="reduceRight" />
-### reduceRight(arr, memo, iterator, callback)
-
-__Alias:__ `foldr`
-
-Same as [`reduce`](#reduce), only operates on `arr` in reverse order.
-
-
----------------------------------------
-
-<a name="detect" />
-### detect(arr, iterator, callback)
-
-Returns the first value in `arr` that passes an async truth test. The
-`iterator` is applied in parallel, meaning the first iterator to return `true` will
-fire the detect `callback` with that result. That means the result might not be
-the first item in the original `arr` (in terms of order) that passes the test.
-
-If order within the original `arr` is important, then look at [`detectSeries`](#detectSeries).
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A truth test to apply to each item in `arr`.
-  The iterator is passed a `callback(truthValue)` which must be called with a 
-  boolean argument once it has completed.
-* `callback(result)` - A callback which is called as soon as any iterator returns
-  `true`, or after all the `iterator` functions have finished. Result will be
-  the first item in the array that passes the truth test (iterator) or the
-  value `undefined` if none passed.
-
-__Example__
-
-```js
-async.detect(['file1','file2','file3'], fs.exists, function(result){
-    // result now equals the first file in the list that exists
-});
-```
-
----------------------------------------
-
-<a name="detectSeries" />
-### detectSeries(arr, iterator, callback)
-
-The same as [`detect`](#detect), only the `iterator` is applied to each item in `arr`
-in series. This means the result is always the first in the original `arr` (in
-terms of array order) that passes the truth test.
-
-
----------------------------------------
-
-<a name="sortBy" />
-### sortBy(arr, iterator, callback)
-
-Sorts a list by the results of running each `arr` value through an async `iterator`.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  The iterator is passed a `callback(err, sortValue)` which must be called once it
-  has completed with an error (which can be `null`) and a value to use as the sort
-  criteria.
-* `callback(err, results)` - A callback which is called after all the `iterator`
-  functions have finished, or an error occurs. Results is the items from
-  the original `arr` sorted by the values returned by the `iterator` calls.
-
-__Example__
-
-```js
-async.sortBy(['file1','file2','file3'], function(file, callback){
-    fs.stat(file, function(err, stats){
-        callback(err, stats.mtime);
-    });
-}, function(err, results){
-    // results is now the original array of files sorted by
-    // modified date
-});
-```
-
-__Sort Order__
-
-By modifying the callback parameter the sorting order can be influenced:
-
-```js
-//ascending order
-async.sortBy([1,9,3,5], function(x, callback){
-    callback(null, x);
-}, function(err,result){
-    //result callback
-} );
-
-//descending order
-async.sortBy([1,9,3,5], function(x, callback){
-    callback(null, x*-1);    //<- x*-1 instead of x, turns the order around
-}, function(err,result){
-    //result callback
-} );
-```
-
----------------------------------------
-
-<a name="some" />
-### some(arr, iterator, callback)
-
-__Alias:__ `any`
-
-Returns `true` if at least one element in the `arr` satisfies an async test.
-_The callback for each iterator call only accepts a single argument of `true` or
-`false`; it does not accept an error argument first!_ This is in-line with the
-way node libraries work with truth tests like `fs.exists`. Once any iterator
-call returns `true`, the main `callback` is immediately called.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A truth test to apply to each item in the array
-  in parallel. The iterator is passed a callback(truthValue) which must be 
-  called with a boolean argument once it has completed.
-* `callback(result)` - A callback which is called as soon as any iterator returns
-  `true`, or after all the iterator functions have finished. Result will be
-  either `true` or `false` depending on the values of the async tests.
-
-__Example__
-
-```js
-async.some(['file1','file2','file3'], fs.exists, function(result){
-    // if result is true then at least one of the files exists
-});
-```
-
----------------------------------------
-
-<a name="every" />
-### every(arr, iterator, callback)
-
-__Alias:__ `all`
-
-Returns `true` if every element in `arr` satisfies an async test.
-_The callback for each `iterator` call only accepts a single argument of `true` or
-`false`; it does not accept an error argument first!_ This is in-line with the
-way node libraries work with truth tests like `fs.exists`.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A truth test to apply to each item in the array
-  in parallel. The iterator is passed a callback(truthValue) which must be 
-  called with a  boolean argument once it has completed.
-* `callback(result)` - A callback which is called after all the `iterator`
-  functions have finished. Result will be either `true` or `false` depending on
-  the values of the async tests.
-
-__Example__
-
-```js
-async.every(['file1','file2','file3'], fs.exists, function(result){
-    // if result is true then every file exists
-});
-```
-
----------------------------------------
-
-<a name="concat" />
-### concat(arr, iterator, callback)
-
-Applies `iterator` to each item in `arr`, concatenating the results. Returns the
-concatenated list. The `iterator`s are called in parallel, and the results are
-concatenated as they return. There is no guarantee that the results array will
-be returned in the original order of `arr` passed to the `iterator` function.
-
-__Arguments__
-
-* `arr` - An array to iterate over.
-* `iterator(item, callback)` - A function to apply to each item in `arr`.
-  The iterator is passed a `callback(err, results)` which must be called once it 
-  has completed with an error (which can be `null`) and an array of results.
-* `callback(err, results)` - A callback which is called after all the `iterator`
-  functions have finished, or an error occurs. Results is an array containing
-  the concatenated results of the `iterator` function.
-
-__Example__
-
-```js
-async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){
-    // files is now a list of filenames that exist in the 3 directories
-});
-```
-
----------------------------------------
-
-<a name="concatSeries" />
-### concatSeries(arr, iterator, callback)
-
-Same as [`concat`](#concat), but executes in series instead of parallel.
-
-
-## Control Flow
-
-<a name="series" />
-### series(tasks, [callback])
-
-Run the functions in the `tasks` array in series, each one running once the previous
-function has completed. If any functions in the series pass an error to its
-callback, no more functions are run, and `callback` is immediately called with the value of the error. 
-Otherwise, `callback` receives an array of results when `tasks` have completed.
-
-It is also possible to use an object instead of an array. Each property will be
-run as a function, and the results will be passed to the final `callback` as an object
-instead of an array. This can be a more readable way of handling results from
-[`series`](#series).
-
-**Note** that while many implementations preserve the order of object properties, the
-[ECMAScript Language Specifcation](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6) 
-explicitly states that
-
-> The mechanics and order of enumerating the properties is not specified.
-
-So if you rely on the order in which your series of functions are executed, and want
-this to work on all platforms, consider using an array. 
-
-__Arguments__
-
-* `tasks` - An array or object containing functions to run, each function is passed
-  a `callback(err, result)` it must call on completion with an error `err` (which can
-  be `null`) and an optional `result` value.
-* `callback(err, results)` - An optional callback to run once all the functions
-  have completed. This function gets a results array (or object) containing all 
-  the result arguments passed to the `task` callbacks.
-
-__Example__
-
-```js
-async.series([
-    function(callback){
-        // do some stuff ...
-        callback(null, 'one');
-    },
-    function(callback){
-        // do some more stuff ...
-        callback(null, 'two');
-    }
-],
-// optional callback
-function(err, results){
-    // results is now equal to ['one', 'two']
-});
-
-
-// an example using an object instead of an array
-async.series({
-    one: function(callback){
-        setTimeout(function(){
-            callback(null, 1);
-        }, 200);
-    },
-    two: function(callback){
-        setTimeout(function(){
-            callback(null, 2);
-        }, 100);
-    }
-},
-function(err, results) {
-    // results is now equal to: {one: 1, two: 2}
-});
-```
-
----------------------------------------
-
-<a name="parallel" />
-### parallel(tasks, [callback])
-
-Run the `tasks` array of functions in parallel, without waiting until the previous
-function has completed. If any of the functions pass an error to its
-callback, the main `callback` is immediately called with the value of the error.
-Once the `tasks` have completed, the results are passed to the final `callback` as an
-array.
-
-It is also possible to use an object instead of an array. Each property will be
-run as a function and the results will be passed to the final `callback` as an object
-instead of an array. This can be a more readable way of handling results from
-[`parallel`](#parallel).
-
-
-__Arguments__
-
-* `tasks` - An array or object containing functions to run. Each function is passed 
-  a `callback(err, result)` which it must call on completion with an error `err` 
-  (which can be `null`) and an optional `result` value.
-* `callback(err, results)` - An optional callback to run once all the functions
-  have completed. This function gets a results array (or object) containing all 
-  the result arguments passed to the task callbacks.
-
-__Example__
-
-```js
-async.parallel([
-    function(callback){
-        setTimeout(function(){
-            callback(null, 'one');
-        }, 200);
-    },
-    function(callback){
-        setTimeout(function(){
-            callback(null, 'two');
-        }, 100);
-    }
-],
-// optional callback
-function(err, results){
-    // the results array will equal ['one','two'] even though
-    // the second function had a shorter timeout.
-});
-
-
-// an example using an object instead of an array
-async.parallel({
-    one: function(callback){
-        setTimeout(function(){
-            callback(null, 1);
-        }, 200);
-    },
-    two: function(callback){
-        setTimeout(function(){
-            callback(null, 2);
-        }, 100);
-    }
-},
-function(err, results) {
-    // results is now equals to: {one: 1, two: 2}
-});
-```
-
----------------------------------------
-
-<a name="parallelLimit" />
-### parallelLimit(tasks, limit, [callback])
-
-The same as [`parallel`](#parallel), only `tasks` are executed in parallel 
-with a maximum of `limit` tasks executing at any time.
-
-Note that the `tasks` are not executed in batches, so there is no guarantee that 
-the first `limit` tasks will complete before any others are started.
-
-__Arguments__
-
-* `tasks` - An array or object containing functions to run, each function is passed 
-  a `callback(err, result)` it must call on completion with an error `err` (which can
-  be `null`) and an optional `result` value.
-* `limit` - The maximum number of `tasks` to run at any time.
-* `callback(err, results)` - An optional callback to run once all the functions
-  have completed. This function gets a results array (or object) containing all 
-  the result arguments passed to the `task` callbacks.
-
----------------------------------------
-
-<a name="whilst" />
-### whilst(test, fn, callback)
-
-Repeatedly call `fn`, while `test` returns `true`. Calls `callback` when stopped,
-or an error occurs.
-
-__Arguments__
-
-* `test()` - synchronous truth test to perform before each execution of `fn`.
-* `fn(callback)` - A function which is called each time `test` passes. The function is
-  passed a `callback(err)`, which must be called once it has completed with an 
-  optional `err` argument.
-* `callback(err)` - A callback which is called after the test fails and repeated
-  execution of `fn` has stopped.
-
-__Example__
-
-```js
-var count = 0;
-
-async.whilst(
-    function () { return count < 5; },
-    function (callback) {
-        count++;
-        setTimeout(callback, 1000);
-    },
-    function (err) {
-        // 5 seconds have passed
-    }
-);
-```
-
----------------------------------------
-
-<a name="doWhilst" />
-### doWhilst(fn, test, callback)
-
-The post-check version of [`whilst`](#whilst). To reflect the difference in 
-the order of operations, the arguments `test` and `fn` are switched. 
-
-`doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
-
----------------------------------------
-
-<a name="until" />
-### until(test, fn, callback)
-
-Repeatedly call `fn` until `test` returns `true`. Calls `callback` when stopped,
-or an error occurs.
-
-The inverse of [`whilst`](#whilst).
-
----------------------------------------
-
-<a name="doUntil" />
-### doUntil(fn, test, callback)
-
-Like [`doWhilst`](#doWhilst), except the `test` is inverted. Note the argument ordering differs from `until`.
-
----------------------------------------
-
-<a name="forever" />
-### forever(fn, errback)
-
-Calls the asynchronous function `fn` with a callback parameter that allows it to
-call itself again, in series, indefinitely.
-
-If an error is passed to the callback then `errback` is called with the
-error, and execution stops, otherwise it will never be called.
-
-```js
-async.forever(
-    function(next) {
-        // next is suitable for passing to things that need a callback(err [, whatever]);
-        // it will result in this function being called again.
-    },
-    function(err) {
-        // if next is called with a value in its first parameter, it will appear
-        // in here as 'err', and execution will stop.
-    }
-);
-```
-
----------------------------------------
-
-<a name="waterfall" />
-### waterfall(tasks, [callback])
-
-Runs the `tasks` array of functions in series, each passing their results to the next in
-the array. However, if any of the `tasks` pass an error to their own callback, the
-next function is not executed, and the main `callback` is immediately called with
-the error.
-
-__Arguments__
-
-* `tasks` - An array of functions to run, each function is passed a 
-  `callback(err, result1, result2, ...)` it must call on completion. The first
-  argument is an error (which can be `null`) and any further arguments will be 
-  passed as arguments in order to the next task.
-* `callback(err, [results])` - An optional callback to run once all the functions
-  have completed. This will be passed the results of the last task's callback.
-
-
-
-__Example__
-
-```js
-async.waterfall([
-    function(callback) {
-        callback(null, 'one', 'two');
-    },
-    function(arg1, arg2, callback) {
-      // arg1 now equals 'one' and arg2 now equals 'two'
-        callback(null, 'three');
-    },
-    function(arg1, callback) {
-        // arg1 now equals 'three'
-        callback(null, 'done');
-    }
-], function (err, result) {
-    // result now equals 'done'    
-});
-```
-
----------------------------------------
-<a name="compose" />
-### compose(fn1, fn2...)
-
-Creates a function which is a composition of the passed asynchronous
-functions. Each function consumes the return value of the function that
-follows. Composing functions `f()`, `g()`, and `h()` would produce the result of
-`f(g(h()))`, only this version uses callbacks to obtain the return values.
-
-Each function is executed with the `this` binding of the composed function.
-
-__Arguments__
-
-* `functions...` - the asynchronous functions to compose
-
-
-__Example__
-
-```js
-function add1(n, callback) {
-    setTimeout(function () {
-        callback(null, n + 1);
-    }, 10);
-}
-
-function mul3(n, callback) {
-    setTimeout(function () {
-        callback(null, n * 3);
-    }, 10);
-}
-
-var add1mul3 = async.compose(mul3, add1);
-
-add1mul3(4, function (err, result) {
-   // result now equals 15
-});
-```
-
----------------------------------------
-<a name="seq" />
-### seq(fn1, fn2...)
-
-Version of the compose function that is more natural to read.
-Each function consumes the return value of the previous function.
-It is the equivalent of [`compose`](#compose) with the arguments reversed.
-
-Each function is executed with the `this` binding of the composed function.
-
-__Arguments__
-
-* functions... - the asynchronous functions to compose
-
-
-__Example__
-
-```js
-// Requires lodash (or underscore), express3 and dresende's orm2.
-// Part of an app, that fetches cats of the logged user.
-// This example uses `seq` function to avoid overnesting and error 
-// handling clutter.
-app.get('/cats', function(request, response) {
-  var User = request.models.User;
-  async.seq(
-    _.bind(User.get, User),  // 'User.get' has signature (id, callback(err, data))
-    function(user, fn) {
-      user.getCats(fn);      // 'getCats' has signature (callback(err, data))
-    }
-  )(req.session.user_id, function (err, cats) {
-    if (err) {
-      console.error(err);
-      response.json({ status: 'error', message: err.message });
-    } else {
-      response.json({ status: 'ok', message: 'Cats found', data: cats });
-    }
-  });
-});
-```
-
----------------------------------------
-<a name="applyEach" />
-### applyEach(fns, args..., callback)
-
-Applies the provided arguments to each function in the array, calling 
-`callback` after all functions have completed. If you only provide the first
-argument, then it will return a function which lets you pass in the
-arguments as if it were a single function call.
-
-__Arguments__
-
-* `fns` - the asynchronous functions to all call with the same arguments
-* `args...` - any number of separate arguments to pass to the function
-* `callback` - the final argument should be the callback, called when all
-  functions have completed processing
-
-
-__Example__
-
-```js
-async.applyEach([enableSearch, updateSchema], 'bucket', callback);
-
-// partial application example:
-async.each(
-    buckets,
-    async.applyEach([enableSearch, updateSchema]),
-    callback
-);
-```
-
----------------------------------------
-
-<a name="applyEachSeries" />
-### applyEachSeries(arr, iterator, callback)
-
-The same as [`applyEach`](#applyEach) only the functions are applied in series.
-
----------------------------------------
-
-<a name="queue" />
-### queue(worker, concurrency)
-
-Creates a `queue` object with the specified `concurrency`. Tasks added to the
-`queue` are processed in parallel (up to the `concurrency` limit). If all
-`worker`s are in progress, the task is queued until one becomes available. 
-Once a `worker` completes a `task`, that `task`'s callback is called.
-
-__Arguments__
-
-* `worker(task, callback)` - An asynchronous function for processing a queued
-  task, which must call its `callback(err)` argument when finished, with an 
-  optional `error` as an argument.
-* `concurrency` - An `integer` for determining how many `worker` functions should be
-  run in parallel.
-
-__Queue objects__
-
-The `queue` object returned by this function has the following properties and
-methods:
-
-* `length()` - a function returning the number of items waiting to be processed.
-* `started` - a function returning whether or not any items have been pushed and processed by the queue
-* `running()` - a function returning the number of items currently being processed.
-* `idle()` - a function returning false if there are items waiting or being processed, or true if not.
-* `concurrency` - an integer for determining how many `worker` functions should be
-  run in parallel. This property can be changed after a `queue` is created to
-  alter the concurrency on-the-fly.
-* `push(task, [callback])` - add a new task to the `queue`. Calls `callback` once 
-  the `worker` has finished processing the task. Instead of a single task, a `tasks` array
-  can be submitted. The respective callback is used for every task in the list.
-* `unshift(task, [callback])` - add a new task to the front of the `queue`.
-* `saturated` - a callback that is called when the `queue` length hits the `concurrency` limit, 
-   and further tasks will be queued.
-* `empty` - a callback that is called when the last item from the `queue` is given to a `worker`.
-* `drain` - a callback that is called when the last item from the `queue` has returned from the `worker`.
-* `paused` - a boolean for determining whether the queue is in a paused state
-* `pause()` - a function that pauses the processing of tasks until `resume()` is called.
-* `resume()` - a function that resumes the processing of queued tasks when the queue is paused.
-* `kill()` - a function that removes the `drain` callback and empties remaining tasks from the queue forcing it to go idle.
-
-__Example__
-
-```js
-// create a queue object with concurrency 2
-
-var q = async.queue(function (task, callback) {
-    console.log('hello ' + task.name);
-    callback();
-}, 2);
-
-
-// assign a callback
-q.drain = function() {
-    console.log('all items have been processed');
-}
-
-// add some items to the queue
-
-q.push({name: 'foo'}, function (err) {
-    console.log('finished processing foo');
-});
-q.push({name: 'bar'}, function (err) {
-    console.log('finished processing bar');
-});
-
-// add some items to the queue (batch-wise)
-
-q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {
-    console.log('finished processing item');
-});
-
-// add some items to the front of the queue
-
-q.unshift({name: 'bar'}, function (err) {
-    console.log('finished processing bar');
-});
-```
-
-
----------------------------------------
-
-<a name="priorityQueue" />
-### priorityQueue(worker, concurrency)
-
-The same as [`queue`](#queue) only tasks are assigned a priority and completed in ascending priority order. There are two differences between `queue` and `priorityQueue` objects:
-
-* `push(task, priority, [callback])` - `priority` should be a number. If an array of
-  `tasks` is given, all tasks will be assigned the same priority.
-* The `unshift` method was removed.
-
----------------------------------------
-
-<a name="cargo" />
-### cargo(worker, [payload])
-
-Creates a `cargo` object with the specified payload. Tasks added to the
-cargo will be processed altogether (up to the `payload` limit). If the
-`worker` is in progress, the task is queued until it becomes available. Once
-the `worker` has completed some tasks, each callback of those tasks is called.
-Check out [this animation](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) for how `cargo` and `queue` work.
-
-While [queue](#queue) passes only one task to one of a group of workers
-at a time, cargo passes an array of tasks to a single worker, repeating
-when the worker is finished.
-
-__Arguments__
-
-* `worker(tasks, callback)` - An asynchronous function for processing an array of
-  queued tasks, which must call its `callback(err)` argument when finished, with 
-  an optional `err` argument.
-* `payload` - An optional `integer` for determining how many tasks should be
-  processed per round; if omitted, the default is unlimited.
-
-__Cargo objects__
-
-The `cargo` object returned by this function has the following properties and
-methods:
-
-* `length()` - A function returning the number of items waiting to be processed.
-* `payload` - An `integer` for determining how many tasks should be
-  process per round. This property can be changed after a `cargo` is created to
-  alter the payload on-the-fly.
-* `push(task, [callback])` - Adds `task` to the `queue`. The callback is called
-  once the `worker` has finished processing the task. Instead of a single task, an array of `tasks` 
-  can be submitted. The respective callback is used for every task in the list.
-* `saturated` - A callback that is called when the `queue.length()` hits the concurrency and further tasks will be queued.
-* `empty` - A callback that is called when the last item from the `queue` is given to a `worker`.
-* `drain` - A callback that is called when the last item from the `queue` has returned from the `worker`.
-
-__Example__
-
-```js
-// create a cargo object with payload 2
-
-var cargo = async.cargo(function (tasks, callback) {
-    for(var i=0; i<tasks.length; i++){
-      console.log('hello ' + tasks[i].name);
-    }
-    callback();
-}, 2);
-
-
-// add some items
-
-cargo.push({name: 'foo'}, function (err) {
-    console.log('finished processing foo');
-});
-cargo.push({name: 'bar'}, function (err) {
-    console.log('finished processing bar');
-});
-cargo.push({name: 'baz'}, function (err) {
-    console.log('finished processing baz');
-});
-```
-
----------------------------------------
-
-<a name="auto" />
-### auto(tasks, [callback])
-
-Determines the best order for running the functions in `tasks`, based on their 
-requirements. Each function can optionally depend on other functions being completed 
-first, and each function is run as soon as its requirements are satisfied. 
-
-If any of the functions pass an error to their callback, it will not 
-complete (so any other functions depending on it will not run), and the main 
-`callback` is immediately called with the error. Functions also receive an 
-object containing the results of functions which have completed so far.
-
-Note, all functions are called with a `results` object as a second argument, 
-so it is unsafe to pass functions in the `tasks` object which cannot handle the
-extra argument. 
-
-For example, this snippet of code:
-
-```js
-async.auto({
-  readData: async.apply(fs.readFile, 'data.txt', 'utf-8')
-}, callback);
-```
-
-will have the effect of calling `readFile` with the results object as the last
-argument, which will fail:
-
-```js
-fs.readFile('data.txt', 'utf-8', cb, {});
-```
-
-Instead, wrap the call to `readFile` in a function which does not forward the 
-`results` object:
-
-```js
-async.auto({
-  readData: function(cb, results){
-    fs.readFile('data.txt', 'utf-8', cb);
-  }
-}, callback);
-```
-
-__Arguments__
-
-* `tasks` - An object. Each of its properties is either a function or an array of
-  requirements, with the function itself the last item in the array. The object's key
-  of a property serves as the name of the task defined by that property,
-  i.e. can be used when specifying requirements for other tasks.
-  The function receives two arguments: (1) a `callback(err, result)` which must be 
-  called when finished, passing an `error` (which can be `null`) and the result of 
-  the function's execution, and (2) a `results` object, containing the results of
-  the previously executed functions.
-* `callback(err, results)` - An optional callback which is called when all the
-  tasks have been completed. It receives the `err` argument if any `tasks` 
-  pass an error to their callback. Results are always returned; however, if 
-  an error occurs, no further `tasks` will be performed, and the results
-  object will only contain partial results.
-
-
-__Example__
-
-```js
-async.auto({
-    get_data: function(callback){
-        console.log('in get_data');
-        // async code to get some data
-        callback(null, 'data', 'converted to array');
-    },
-    make_folder: function(callback){
-        console.log('in make_folder');
-        // async code to create a directory to store a file in
-        // this is run at the same time as getting the data
-        callback(null, 'folder');
-    },
-    write_file: ['get_data', 'make_folder', function(callback, results){
-        console.log('in write_file', JSON.stringify(results));
-        // once there is some data and the directory exists,
-        // write the data to a file in the directory
-        callback(null, 'filename');
-    }],
-    email_link: ['write_file', function(callback, results){
-        console.log('in email_link', JSON.stringify(results));
-        // once the file is written let's email a link to it...
-        // results.write_file contains the filename returned by write_file.
-        callback(null, {'file':results.write_file, 'email':'user@example.com'});
-    }]
-}, function(err, results) {
-    console.log('err = ', err);
-    console.log('results = ', results);
-});
-```
-
-This is a fairly trivial example, but to do this using the basic parallel and
-series functions would look like this:
-
-```js
-async.parallel([
-    function(callback){
-        console.log('in get_data');
-        // async code to get some data
-        callback(null, 'data', 'converted to array');
-    },
-    function(callback){
-        console.log('in make_folder');
-        // async code to create a directory to store a file in
-        // this is run at the same time as getting the data
-        callback(null, 'folder');
-    }
-],
-function(err, results){
-    async.series([
-        function(callback){
-            console.log('in write_file', JSON.stringify(results));
-            // once there is some data and the directory exists,
-            // write the data to a file in the directory
-            results.push('filename');
-            callback(null);
-        },
-        function(callback){
-            console.log('in email_link', JSON.stringify(results));
-            // once the file is written let's email a link to it...
-            callback(null, {'file':results.pop(), 'email':'user@example.com'});
+// for use with Node-style callbacks...
+var async = require("async");
+
+var obj = {dev: "/dev.json", test: "/test.json", prod: "/prod.json"};
+var configs = {};
+
+async.forEachOf(obj, (value, key, callback) => {
+    fs.readFile(__dirname + value, "utf8", (err, data) => {
+        if (err) return callback(err);
+        try {
+            configs[key] = JSON.parse(data);
+        } catch (e) {
+            return callback(e);
         }
-    ]);
-});
-```
-
-For a complicated series of `async` tasks, using the [`auto`](#auto) function makes adding
-new tasks much easier (and the code more readable).
-
-
----------------------------------------
-
-<a name="retry" />
-### retry([times = 5], task, [callback])
-
-Attempts to get a successful response from `task` no more than `times` times before
-returning an error. If the task is successful, the `callback` will be passed the result
-of the successful task. If all attempts fail, the callback will be passed the error and
-result (if any) of the final attempt.
-
-__Arguments__
-
-* `times` - An integer indicating how many times to attempt the `task` before giving up. Defaults to 5.
-* `task(callback, results)` - A function which receives two arguments: (1) a `callback(err, result)`
-  which must be called when finished, passing `err` (which can be `null`) and the `result` of 
-  the function's execution, and (2) a `results` object, containing the results of
-  the previously executed functions (if nested inside another control flow).
-* `callback(err, results)` - An optional callback which is called when the
-  task has succeeded, or after the final failed attempt. It receives the `err` and `result` arguments of the last attempt at completing the `task`.
-
-The [`retry`](#retry) function can be used as a stand-alone control flow by passing a
-callback, as shown below:
-
-```js
-async.retry(3, apiMethod, function(err, result) {
-    // do something with the result
-});
-```
-
-It can also be embeded within other control flow functions to retry individual methods
-that are not as reliable, like this:
-
-```js
-async.auto({
-    users: api.getUsers.bind(api),
-    payments: async.retry(3, api.getPayments.bind(api))
-}, function(err, results) {
-  // do something with the results
-});
-```
-
-
----------------------------------------
-
-<a name="iterator" />
-### iterator(tasks)
-
-Creates an iterator function which calls the next function in the `tasks` array,
-returning a continuation to call the next one after that. It's also possible to
-“peek” at the next iterator with `iterator.next()`.
-
-This function is used internally by the `async` module, but can be useful when
-you want to manually control the flow of functions in series.
-
-__Arguments__
-
-* `tasks` - An array of functions to run.
-
-__Example__
-
-```js
-var iterator = async.iterator([
-    function(){ sys.p('one'); },
-    function(){ sys.p('two'); },
-    function(){ sys.p('three'); }
-]);
-
-node> var iterator2 = iterator();
-'one'
-node> var iterator3 = iterator2();
-'two'
-node> iterator3();
-'three'
-node> var nextfn = iterator2.next();
-node> nextfn();
-'three'
-```
-
----------------------------------------
-
-<a name="apply" />
-### apply(function, arguments..)
-
-Creates a continuation function with some arguments already applied. 
-
-Useful as a shorthand when combined with other control flow functions. Any arguments
-passed to the returned function are added to the arguments originally passed
-to apply.
-
-__Arguments__
-
-* `function` - The function you want to eventually apply all arguments to.
-* `arguments...` - Any number of arguments to automatically apply when the
-  continuation is called.
-
-__Example__
-
-```js
-// using apply
-
-async.parallel([
-    async.apply(fs.writeFile, 'testfile1', 'test1'),
-    async.apply(fs.writeFile, 'testfile2', 'test2'),
-]);
-
-
-// the same process without using apply
-
-async.parallel([
-    function(callback){
-        fs.writeFile('testfile1', 'test1', callback);
-    },
-    function(callback){
-        fs.writeFile('testfile2', 'test2', callback);
-    }
-]);
-```
-
-It's possible to pass any number of additional arguments when calling the
-continuation:
-
-```js
-node> var fn = async.apply(sys.puts, 'one');
-node> fn('two', 'three');
-one
-two
-three
-```
-
----------------------------------------
-
-<a name="nextTick" />
-### nextTick(callback), setImmediate(callback)
-
-Calls `callback` on a later loop around the event loop. In Node.js this just
-calls `process.nextTick`; in the browser it falls back to `setImmediate(callback)`
-if available, otherwise `setTimeout(callback, 0)`, which means other higher priority
-events may precede the execution of `callback`.
-
-This is used internally for browser-compatibility purposes.
-
-__Arguments__
-
-* `callback` - The function to call on a later loop around the event loop.
-
-__Example__
-
-```js
-var call_order = [];
-async.nextTick(function(){
-    call_order.push('two');
-    // call_order now equals ['one','two']
-});
-call_order.push('one')
-```
-
-<a name="times" />
-### times(n, callback)
-
-Calls the `callback` function `n` times, and accumulates results in the same manner
-you would use with [`map`](#map).
-
-__Arguments__
-
-* `n` - The number of times to run the function.
-* `callback` - The function to call `n` times.
-
-__Example__
-
-```js
-// Pretend this is some complicated async factory
-var createUser = function(id, callback) {
-  callback(null, {
-    id: 'user' + id
-  })
-}
-// generate 5 users
-async.times(5, function(n, next){
-    createUser(n, function(err, user) {
-      next(err, user)
-    })
-}, function(err, users) {
-  // we should now have 5 users
-});
-```
-
-<a name="timesSeries" />
-### timesSeries(n, callback)
-
-The same as [`times`](#times), only the iterator is applied to each item in `arr` in
-series. The next `iterator` is only called once the current one has completed. 
-The results array will be in the same order as the original.
-
-
-## Utils
-
-<a name="memoize" />
-### memoize(fn, [hasher])
-
-Caches the results of an `async` function. When creating a hash to store function
-results against, the callback is omitted from the hash and an optional hash
-function can be used.
-
-The cache of results is exposed as the `memo` property of the function returned
-by `memoize`.
-
-__Arguments__
-
-* `fn` - The function to proxy and cache results from.
-* `hasher` - Tn optional function for generating a custom hash for storing
-  results. It has all the arguments applied to it apart from the callback, and
-  must be synchronous.
-
-__Example__
-
-```js
-var slow_fn = function (name, callback) {
-    // do something
-    callback(null, result);
-};
-var fn = async.memoize(slow_fn);
-
-// fn can now be used as if it were slow_fn
-fn('some name', function () {
-    // callback
+        callback();
+    });
+}, err => {
+    if (err) console.error(err.message);
+    // configs is now a map of JSON data
+    doSomethingWith(configs);
 });
 ```
 
-<a name="unmemoize" />
-### unmemoize(fn)
-
-Undoes a [`memoize`](#memoize)d function, reverting it to the original, unmemoized
-form. Handy for testing.
-
-__Arguments__
-
-* `fn` - the memoized function
-
-<a name="log" />
-### log(function, arguments)
-
-Logs the result of an `async` function to the `console`. Only works in Node.js or
-in browsers that support `console.log` and `console.error` (such as FF and Chrome).
-If multiple arguments are returned from the async function, `console.log` is
-called on each argument in order.
-
-__Arguments__
-
-* `function` - The function you want to eventually apply all arguments to.
-* `arguments...` - Any number of arguments to apply to the function.
-
-__Example__
-
-```js
-var hello = function(name, callback){
-    setTimeout(function(){
-        callback(null, 'hello ' + name);
-    }, 1000);
-};
-```
-```js
-node> async.log(hello, 'world');
-'hello world'
-```
-
----------------------------------------
-
-<a name="dir" />
-### dir(function, arguments)
-
-Logs the result of an `async` function to the `console` using `console.dir` to
-display the properties of the resulting object. Only works in Node.js or
-in browsers that support `console.dir` and `console.error` (such as FF and Chrome).
-If multiple arguments are returned from the async function, `console.dir` is
-called on each argument in order.
-
-__Arguments__
-
-* `function` - The function you want to eventually apply all arguments to.
-* `arguments...` - Any number of arguments to apply to the function.
-
-__Example__
-
-```js
-var hello = function(name, callback){
-    setTimeout(function(){
-        callback(null, {hello: name});
-    }, 1000);
-};
-```
-```js
-node> async.dir(hello, 'world');
-{hello: 'world'}
+```javascript
+var async = require("async");
+
+// ...or ES2017 async functions
+async.mapLimit(urls, 5, async function(url) {
+    const response = await fetch(url)
+    return response.body
+}, (err, results) => {
+    if (err) throw err
+    // results is now an array of the response bodies
+    console.log(results)
+})
 ```
-
----------------------------------------
-
-<a name="noConflict" />
-### noConflict()
-
-Changes the value of `async` back to its original value, returning a reference to the
-`async` object.
diff --git a/node_modules/async/all.js b/node_modules/async/all.js
new file mode 100644
index 0000000000000000000000000000000000000000..148db6836d0f1704ee2dabd5cef96b4ccc177570
--- /dev/null
+++ b/node_modules/async/all.js
@@ -0,0 +1,119 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Returns `true` if every element in `coll` satisfies an async test. If any
+ * iteratee call returns `false`, the main `callback` is immediately called.
+ *
+ * @name every
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias all
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collection in parallel.
+ * The iteratee must complete with a boolean result value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result will be either `true` or `false`
+ * depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file5.txt'];
+ * const withMissingFileList = ['file1.txt','file2.txt','file4.txt'];
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.every(fileList, fileExists, function(err, result) {
+ *     console.log(result);
+ *     // true
+ *     // result is true since every file exists
+ * });
+ *
+ * async.every(withMissingFileList, fileExists, function(err, result) {
+ *     console.log(result);
+ *     // false
+ *     // result is false since NOT every file exists
+ * });
+ *
+ * // Using Promises
+ * async.every(fileList, fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // true
+ *     // result is true since every file exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * async.every(withMissingFileList, fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // false
+ *     // result is false since NOT every file exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.every(fileList, fileExists);
+ *         console.log(result);
+ *         // true
+ *         // result is true since every file exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * async () => {
+ *     try {
+ *         let result = await async.every(withMissingFileList, fileExists);
+ *         console.log(result);
+ *         // false
+ *         // result is false since NOT every file exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function every(coll, iteratee, callback) {
+  return (0, _createTester2.default)(bool => !bool, res => !res)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(every, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/allLimit.js b/node_modules/async/allLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..25b2c089cf6f50e7b32194f23df3ef54da1e8289
--- /dev/null
+++ b/node_modules/async/allLimit.js
@@ -0,0 +1,46 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name everyLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.every]{@link module:Collections.every}
+ * @alias allLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collection in parallel.
+ * The iteratee must complete with a boolean result value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result will be either `true` or `false`
+ * depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function everyLimit(coll, limit, iteratee, callback) {
+  return (0, _createTester2.default)(bool => !bool, res => !res)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(everyLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/allSeries.js b/node_modules/async/allSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..147c3dc56fc5b704af935c68bf57fd27e70da1d8
--- /dev/null
+++ b/node_modules/async/allSeries.js
@@ -0,0 +1,45 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time.
+ *
+ * @name everySeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.every]{@link module:Collections.every}
+ * @alias allSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collection in series.
+ * The iteratee must complete with a boolean result value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result will be either `true` or `false`
+ * depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function everySeries(coll, iteratee, callback) {
+  return (0, _createTester2.default)(bool => !bool, res => !res)(_eachOfSeries2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(everySeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/any.js b/node_modules/async/any.js
new file mode 100644
index 0000000000000000000000000000000000000000..2046cf640252a7898e9eba24d1b8a50130ff72a6
--- /dev/null
+++ b/node_modules/async/any.js
@@ -0,0 +1,122 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Returns `true` if at least one element in the `coll` satisfies an async test.
+ * If any iteratee call returns `true`, the main `callback` is immediately
+ * called.
+ *
+ * @name some
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias any
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collections in parallel.
+ * The iteratee should complete with a boolean `result` value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the iteratee functions have finished.
+ * Result will be either `true` or `false` depending on the values of the async
+ * tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists,
+ *    function(err, result) {
+ *        console.log(result);
+ *        // true
+ *        // result is true since some file in the list exists
+ *    }
+ *);
+ *
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists,
+ *    function(err, result) {
+ *        console.log(result);
+ *        // false
+ *        // result is false since none of the files exists
+ *    }
+ *);
+ *
+ * // Using Promises
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // true
+ *     // result is true since some file in the list exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // false
+ *     // result is false since none of the files exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists);
+ *         console.log(result);
+ *         // true
+ *         // result is true since some file in the list exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * async () => {
+ *     try {
+ *         let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists);
+ *         console.log(result);
+ *         // false
+ *         // result is false since none of the files exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function some(coll, iteratee, callback) {
+  return (0, _createTester2.default)(Boolean, res => res)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(some, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/anyLimit.js b/node_modules/async/anyLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..c8a295a8b4f760d468be496af58b4b6d126219ec
--- /dev/null
+++ b/node_modules/async/anyLimit.js
@@ -0,0 +1,47 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name someLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.some]{@link module:Collections.some}
+ * @alias anyLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collections in parallel.
+ * The iteratee should complete with a boolean `result` value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the iteratee functions have finished.
+ * Result will be either `true` or `false` depending on the values of the async
+ * tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function someLimit(coll, limit, iteratee, callback) {
+  return (0, _createTester2.default)(Boolean, res => res)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(someLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/anySeries.js b/node_modules/async/anySeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..ee0654ba69fafcecbc398624e6b71b2b109268a8
--- /dev/null
+++ b/node_modules/async/anySeries.js
@@ -0,0 +1,46 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time.
+ *
+ * @name someSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.some]{@link module:Collections.some}
+ * @alias anySeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collections in series.
+ * The iteratee should complete with a boolean `result` value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the iteratee functions have finished.
+ * Result will be either `true` or `false` depending on the values of the async
+ * tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function someSeries(coll, iteratee, callback) {
+  return (0, _createTester2.default)(Boolean, res => res)(_eachOfSeries2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(someSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/apply.js b/node_modules/async/apply.js
new file mode 100644
index 0000000000000000000000000000000000000000..5246833a12b6f41013697653439fc5e03cd1fa49
--- /dev/null
+++ b/node_modules/async/apply.js
@@ -0,0 +1,55 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+exports.default = function (fn, ...args) {
+  return (...callArgs) => fn(...args, ...callArgs);
+};
+
+module.exports = exports["default"]; /**
+                                      * Creates a continuation function with some arguments already applied.
+                                      *
+                                      * Useful as a shorthand when combined with other control flow functions. Any
+                                      * arguments passed to the returned function are added to the arguments
+                                      * originally passed to apply.
+                                      *
+                                      * @name apply
+                                      * @static
+                                      * @memberOf module:Utils
+                                      * @method
+                                      * @category Util
+                                      * @param {Function} fn - The function you want to eventually apply all
+                                      * arguments to. Invokes with (arguments...).
+                                      * @param {...*} arguments... - Any number of arguments to automatically apply
+                                      * when the continuation is called.
+                                      * @returns {Function} the partially-applied function
+                                      * @example
+                                      *
+                                      * // using apply
+                                      * async.parallel([
+                                      *     async.apply(fs.writeFile, 'testfile1', 'test1'),
+                                      *     async.apply(fs.writeFile, 'testfile2', 'test2')
+                                      * ]);
+                                      *
+                                      *
+                                      * // the same process without using apply
+                                      * async.parallel([
+                                      *     function(callback) {
+                                      *         fs.writeFile('testfile1', 'test1', callback);
+                                      *     },
+                                      *     function(callback) {
+                                      *         fs.writeFile('testfile2', 'test2', callback);
+                                      *     }
+                                      * ]);
+                                      *
+                                      * // It's possible to pass any number of additional arguments when calling the
+                                      * // continuation:
+                                      *
+                                      * node> var fn = async.apply(sys.puts, 'one');
+                                      * node> fn('two', 'three');
+                                      * one
+                                      * two
+                                      * three
+                                      */
\ No newline at end of file
diff --git a/node_modules/async/applyEach.js b/node_modules/async/applyEach.js
new file mode 100644
index 0000000000000000000000000000000000000000..b08c6701315278e1b3e826293bdffc71426f2d4a
--- /dev/null
+++ b/node_modules/async/applyEach.js
@@ -0,0 +1,57 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _applyEach = require('./internal/applyEach.js');
+
+var _applyEach2 = _interopRequireDefault(_applyEach);
+
+var _map = require('./map.js');
+
+var _map2 = _interopRequireDefault(_map);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Applies the provided arguments to each function in the array, calling
+ * `callback` after all functions have completed. If you only provide the first
+ * argument, `fns`, then it will return a function which lets you pass in the
+ * arguments as if it were a single function call. If more arguments are
+ * provided, `callback` is required while `args` is still optional. The results
+ * for each of the applied async functions are passed to the final callback
+ * as an array.
+ *
+ * @name applyEach
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s
+ * to all call with the same arguments
+ * @param {...*} [args] - any number of separate arguments to pass to the
+ * function.
+ * @param {Function} [callback] - the final argument should be the callback,
+ * called when all functions have completed processing.
+ * @returns {AsyncFunction} - Returns a function that takes no args other than
+ * an optional callback, that is the result of applying the `args` to each
+ * of the functions.
+ * @example
+ *
+ * const appliedFn = async.applyEach([enableSearch, updateSchema], 'bucket')
+ *
+ * appliedFn((err, results) => {
+ *     // results[0] is the results for `enableSearch`
+ *     // results[1] is the results for `updateSchema`
+ * });
+ *
+ * // partial application example:
+ * async.each(
+ *     buckets,
+ *     async (bucket) => async.applyEach([enableSearch, updateSchema], bucket)(),
+ *     callback
+ * );
+ */
+exports.default = (0, _applyEach2.default)(_map2.default);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/applyEachSeries.js b/node_modules/async/applyEachSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..6a19ca3f7bf994ad54f1950839d5f2d45211c357
--- /dev/null
+++ b/node_modules/async/applyEachSeries.js
@@ -0,0 +1,37 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _applyEach = require('./internal/applyEach.js');
+
+var _applyEach2 = _interopRequireDefault(_applyEach);
+
+var _mapSeries = require('./mapSeries.js');
+
+var _mapSeries2 = _interopRequireDefault(_mapSeries);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`applyEach`]{@link module:ControlFlow.applyEach} but runs only a single async operation at a time.
+ *
+ * @name applyEachSeries
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.applyEach]{@link module:ControlFlow.applyEach}
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s to all
+ * call with the same arguments
+ * @param {...*} [args] - any number of separate arguments to pass to the
+ * function.
+ * @param {Function} [callback] - the final argument should be the callback,
+ * called when all functions have completed processing.
+ * @returns {AsyncFunction} - A function, that when called, is the result of
+ * appling the `args` to the list of functions.  It takes no args, other than
+ * a callback.
+ */
+exports.default = (0, _applyEach2.default)(_mapSeries2.default);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/asyncify.js b/node_modules/async/asyncify.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c3bf886b2e6957e2b926af6cd9e83324960821c
--- /dev/null
+++ b/node_modules/async/asyncify.js
@@ -0,0 +1,118 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = asyncify;
+
+var _initialParams = require('./internal/initialParams.js');
+
+var _initialParams2 = _interopRequireDefault(_initialParams);
+
+var _setImmediate = require('./internal/setImmediate.js');
+
+var _setImmediate2 = _interopRequireDefault(_setImmediate);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Take a sync function and make it async, passing its return value to a
+ * callback. This is useful for plugging sync functions into a waterfall,
+ * series, or other async functions. Any arguments passed to the generated
+ * function will be passed to the wrapped function (except for the final
+ * callback argument). Errors thrown will be passed to the callback.
+ *
+ * If the function passed to `asyncify` returns a Promise, that promises's
+ * resolved/rejected state will be used to call the callback, rather than simply
+ * the synchronous return value.
+ *
+ * This also means you can asyncify ES2017 `async` functions.
+ *
+ * @name asyncify
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @alias wrapSync
+ * @category Util
+ * @param {Function} func - The synchronous function, or Promise-returning
+ * function to convert to an {@link AsyncFunction}.
+ * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be
+ * invoked with `(args..., callback)`.
+ * @example
+ *
+ * // passing a regular synchronous function
+ * async.waterfall([
+ *     async.apply(fs.readFile, filename, "utf8"),
+ *     async.asyncify(JSON.parse),
+ *     function (data, next) {
+ *         // data is the result of parsing the text.
+ *         // If there was a parsing error, it would have been caught.
+ *     }
+ * ], callback);
+ *
+ * // passing a function returning a promise
+ * async.waterfall([
+ *     async.apply(fs.readFile, filename, "utf8"),
+ *     async.asyncify(function (contents) {
+ *         return db.model.create(contents);
+ *     }),
+ *     function (model, next) {
+ *         // `model` is the instantiated model object.
+ *         // If there was an error, this function would be skipped.
+ *     }
+ * ], callback);
+ *
+ * // es2017 example, though `asyncify` is not needed if your JS environment
+ * // supports async functions out of the box
+ * var q = async.queue(async.asyncify(async function(file) {
+ *     var intermediateStep = await processFile(file);
+ *     return await somePromise(intermediateStep)
+ * }));
+ *
+ * q.push(files);
+ */
+function asyncify(func) {
+    if ((0, _wrapAsync.isAsync)(func)) {
+        return function (...args /*, callback*/) {
+            const callback = args.pop();
+            const promise = func.apply(this, args);
+            return handlePromise(promise, callback);
+        };
+    }
+
+    return (0, _initialParams2.default)(function (args, callback) {
+        var result;
+        try {
+            result = func.apply(this, args);
+        } catch (e) {
+            return callback(e);
+        }
+        // if result is Promise object
+        if (result && typeof result.then === 'function') {
+            return handlePromise(result, callback);
+        } else {
+            callback(null, result);
+        }
+    });
+}
+
+function handlePromise(promise, callback) {
+    return promise.then(value => {
+        invokeCallback(callback, null, value);
+    }, err => {
+        invokeCallback(callback, err && err.message ? err : new Error(err));
+    });
+}
+
+function invokeCallback(callback, error, value) {
+    try {
+        callback(error, value);
+    } catch (err) {
+        (0, _setImmediate2.default)(e => {
+            throw e;
+        }, err);
+    }
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/auto.js b/node_modules/async/auto.js
new file mode 100644
index 0000000000000000000000000000000000000000..c4a85d432b38723f6a4e40a282e533ca94a8c416
--- /dev/null
+++ b/node_modules/async/auto.js
@@ -0,0 +1,333 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = auto;
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _onlyOnce = require('./internal/onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _promiseCallback = require('./internal/promiseCallback.js');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on
+ * their requirements. Each function can optionally depend on other functions
+ * being completed first, and each function is run as soon as its requirements
+ * are satisfied.
+ *
+ * If any of the {@link AsyncFunction}s pass an error to their callback, the `auto` sequence
+ * will stop. Further tasks will not execute (so any other functions depending
+ * on it will not run), and the main `callback` is immediately called with the
+ * error.
+ *
+ * {@link AsyncFunction}s also receive an object containing the results of functions which
+ * have completed so far as the first argument, if they have dependencies. If a
+ * task function has no dependencies, it will only be passed a callback.
+ *
+ * @name auto
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Object} tasks - An object. Each of its properties is either a
+ * function or an array of requirements, with the {@link AsyncFunction} itself the last item
+ * in the array. The object's key of a property serves as the name of the task
+ * defined by that property, i.e. can be used when specifying requirements for
+ * other tasks. The function receives one or two arguments:
+ * * a `results` object, containing the results of the previously executed
+ *   functions, only passed if the task has any dependencies,
+ * * a `callback(err, result)` function, which must be called when finished,
+ *   passing an `error` (which can be `null`) and the result of the function's
+ *   execution.
+ * @param {number} [concurrency=Infinity] - An optional `integer` for
+ * determining the maximum number of tasks that can be run in parallel. By
+ * default, as many as possible.
+ * @param {Function} [callback] - An optional callback which is called when all
+ * the tasks have been completed. It receives the `err` argument if any `tasks`
+ * pass an error to their callback. Results are always returned; however, if an
+ * error occurs, no further `tasks` will be performed, and the results object
+ * will only contain partial results. Invoked with (err, results).
+ * @returns {Promise} a promise, if a callback is not passed
+ * @example
+ *
+ * //Using Callbacks
+ * async.auto({
+ *     get_data: function(callback) {
+ *         // async code to get some data
+ *         callback(null, 'data', 'converted to array');
+ *     },
+ *     make_folder: function(callback) {
+ *         // async code to create a directory to store a file in
+ *         // this is run at the same time as getting the data
+ *         callback(null, 'folder');
+ *     },
+ *     write_file: ['get_data', 'make_folder', function(results, callback) {
+ *         // once there is some data and the directory exists,
+ *         // write the data to a file in the directory
+ *         callback(null, 'filename');
+ *     }],
+ *     email_link: ['write_file', function(results, callback) {
+ *         // once the file is written let's email a link to it...
+ *         callback(null, {'file':results.write_file, 'email':'user@example.com'});
+ *     }]
+ * }, function(err, results) {
+ *     if (err) {
+ *         console.log('err = ', err);
+ *     }
+ *     console.log('results = ', results);
+ *     // results = {
+ *     //     get_data: ['data', 'converted to array']
+ *     //     make_folder; 'folder',
+ *     //     write_file: 'filename'
+ *     //     email_link: { file: 'filename', email: 'user@example.com' }
+ *     // }
+ * });
+ *
+ * //Using Promises
+ * async.auto({
+ *     get_data: function(callback) {
+ *         console.log('in get_data');
+ *         // async code to get some data
+ *         callback(null, 'data', 'converted to array');
+ *     },
+ *     make_folder: function(callback) {
+ *         console.log('in make_folder');
+ *         // async code to create a directory to store a file in
+ *         // this is run at the same time as getting the data
+ *         callback(null, 'folder');
+ *     },
+ *     write_file: ['get_data', 'make_folder', function(results, callback) {
+ *         // once there is some data and the directory exists,
+ *         // write the data to a file in the directory
+ *         callback(null, 'filename');
+ *     }],
+ *     email_link: ['write_file', function(results, callback) {
+ *         // once the file is written let's email a link to it...
+ *         callback(null, {'file':results.write_file, 'email':'user@example.com'});
+ *     }]
+ * }).then(results => {
+ *     console.log('results = ', results);
+ *     // results = {
+ *     //     get_data: ['data', 'converted to array']
+ *     //     make_folder; 'folder',
+ *     //     write_file: 'filename'
+ *     //     email_link: { file: 'filename', email: 'user@example.com' }
+ *     // }
+ * }).catch(err => {
+ *     console.log('err = ', err);
+ * });
+ *
+ * //Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.auto({
+ *             get_data: function(callback) {
+ *                 // async code to get some data
+ *                 callback(null, 'data', 'converted to array');
+ *             },
+ *             make_folder: function(callback) {
+ *                 // async code to create a directory to store a file in
+ *                 // this is run at the same time as getting the data
+ *                 callback(null, 'folder');
+ *             },
+ *             write_file: ['get_data', 'make_folder', function(results, callback) {
+ *                 // once there is some data and the directory exists,
+ *                 // write the data to a file in the directory
+ *                 callback(null, 'filename');
+ *             }],
+ *             email_link: ['write_file', function(results, callback) {
+ *                 // once the file is written let's email a link to it...
+ *                 callback(null, {'file':results.write_file, 'email':'user@example.com'});
+ *             }]
+ *         });
+ *         console.log('results = ', results);
+ *         // results = {
+ *         //     get_data: ['data', 'converted to array']
+ *         //     make_folder; 'folder',
+ *         //     write_file: 'filename'
+ *         //     email_link: { file: 'filename', email: 'user@example.com' }
+ *         // }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function auto(tasks, concurrency, callback) {
+    if (typeof concurrency !== 'number') {
+        // concurrency is optional, shift the args.
+        callback = concurrency;
+        concurrency = null;
+    }
+    callback = (0, _once2.default)(callback || (0, _promiseCallback.promiseCallback)());
+    var numTasks = Object.keys(tasks).length;
+    if (!numTasks) {
+        return callback(null);
+    }
+    if (!concurrency) {
+        concurrency = numTasks;
+    }
+
+    var results = {};
+    var runningTasks = 0;
+    var canceled = false;
+    var hasError = false;
+
+    var listeners = Object.create(null);
+
+    var readyTasks = [];
+
+    // for cycle detection:
+    var readyToCheck = []; // tasks that have been identified as reachable
+    // without the possibility of returning to an ancestor task
+    var uncheckedDependencies = {};
+
+    Object.keys(tasks).forEach(key => {
+        var task = tasks[key];
+        if (!Array.isArray(task)) {
+            // no dependencies
+            enqueueTask(key, [task]);
+            readyToCheck.push(key);
+            return;
+        }
+
+        var dependencies = task.slice(0, task.length - 1);
+        var remainingDependencies = dependencies.length;
+        if (remainingDependencies === 0) {
+            enqueueTask(key, task);
+            readyToCheck.push(key);
+            return;
+        }
+        uncheckedDependencies[key] = remainingDependencies;
+
+        dependencies.forEach(dependencyName => {
+            if (!tasks[dependencyName]) {
+                throw new Error('async.auto task `' + key + '` has a non-existent dependency `' + dependencyName + '` in ' + dependencies.join(', '));
+            }
+            addListener(dependencyName, () => {
+                remainingDependencies--;
+                if (remainingDependencies === 0) {
+                    enqueueTask(key, task);
+                }
+            });
+        });
+    });
+
+    checkForDeadlocks();
+    processQueue();
+
+    function enqueueTask(key, task) {
+        readyTasks.push(() => runTask(key, task));
+    }
+
+    function processQueue() {
+        if (canceled) return;
+        if (readyTasks.length === 0 && runningTasks === 0) {
+            return callback(null, results);
+        }
+        while (readyTasks.length && runningTasks < concurrency) {
+            var run = readyTasks.shift();
+            run();
+        }
+    }
+
+    function addListener(taskName, fn) {
+        var taskListeners = listeners[taskName];
+        if (!taskListeners) {
+            taskListeners = listeners[taskName] = [];
+        }
+
+        taskListeners.push(fn);
+    }
+
+    function taskComplete(taskName) {
+        var taskListeners = listeners[taskName] || [];
+        taskListeners.forEach(fn => fn());
+        processQueue();
+    }
+
+    function runTask(key, task) {
+        if (hasError) return;
+
+        var taskCallback = (0, _onlyOnce2.default)((err, ...result) => {
+            runningTasks--;
+            if (err === false) {
+                canceled = true;
+                return;
+            }
+            if (result.length < 2) {
+                [result] = result;
+            }
+            if (err) {
+                var safeResults = {};
+                Object.keys(results).forEach(rkey => {
+                    safeResults[rkey] = results[rkey];
+                });
+                safeResults[key] = result;
+                hasError = true;
+                listeners = Object.create(null);
+                if (canceled) return;
+                callback(err, safeResults);
+            } else {
+                results[key] = result;
+                taskComplete(key);
+            }
+        });
+
+        runningTasks++;
+        var taskFn = (0, _wrapAsync2.default)(task[task.length - 1]);
+        if (task.length > 1) {
+            taskFn(results, taskCallback);
+        } else {
+            taskFn(taskCallback);
+        }
+    }
+
+    function checkForDeadlocks() {
+        // Kahn's algorithm
+        // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
+        // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html
+        var currentTask;
+        var counter = 0;
+        while (readyToCheck.length) {
+            currentTask = readyToCheck.pop();
+            counter++;
+            getDependents(currentTask).forEach(dependent => {
+                if (--uncheckedDependencies[dependent] === 0) {
+                    readyToCheck.push(dependent);
+                }
+            });
+        }
+
+        if (counter !== numTasks) {
+            throw new Error('async.auto cannot execute tasks due to a recursive dependency');
+        }
+    }
+
+    function getDependents(taskName) {
+        var result = [];
+        Object.keys(tasks).forEach(key => {
+            const task = tasks[key];
+            if (Array.isArray(task) && task.indexOf(taskName) >= 0) {
+                result.push(key);
+            }
+        });
+        return result;
+    }
+
+    return callback[_promiseCallback.PROMISE_SYMBOL];
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/autoInject.js b/node_modules/async/autoInject.js
new file mode 100644
index 0000000000000000000000000000000000000000..393baad6d93215ade5b80f96c55bed8760138a21
--- /dev/null
+++ b/node_modules/async/autoInject.js
@@ -0,0 +1,182 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = autoInject;
+
+var _auto = require('./auto.js');
+
+var _auto2 = _interopRequireDefault(_auto);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+var FN_ARGS = /^(?:async\s+)?(?:function)?\s*\w*\s*\(\s*([^)]+)\s*\)(?:\s*{)/;
+var ARROW_FN_ARGS = /^(?:async\s+)?\(?\s*([^)=]+)\s*\)?(?:\s*=>)/;
+var FN_ARG_SPLIT = /,/;
+var FN_ARG = /(=.+)?(\s*)$/;
+
+function stripComments(string) {
+    let stripped = '';
+    let index = 0;
+    let endBlockComment = string.indexOf('*/');
+    while (index < string.length) {
+        if (string[index] === '/' && string[index + 1] === '/') {
+            // inline comment
+            let endIndex = string.indexOf('\n', index);
+            index = endIndex === -1 ? string.length : endIndex;
+        } else if (endBlockComment !== -1 && string[index] === '/' && string[index + 1] === '*') {
+            // block comment
+            let endIndex = string.indexOf('*/', index);
+            if (endIndex !== -1) {
+                index = endIndex + 2;
+                endBlockComment = string.indexOf('*/', index);
+            } else {
+                stripped += string[index];
+                index++;
+            }
+        } else {
+            stripped += string[index];
+            index++;
+        }
+    }
+    return stripped;
+}
+
+function parseParams(func) {
+    const src = stripComments(func.toString());
+    let match = src.match(FN_ARGS);
+    if (!match) {
+        match = src.match(ARROW_FN_ARGS);
+    }
+    if (!match) throw new Error('could not parse args in autoInject\nSource:\n' + src);
+    let [, args] = match;
+    return args.replace(/\s/g, '').split(FN_ARG_SPLIT).map(arg => arg.replace(FN_ARG, '').trim());
+}
+
+/**
+ * A dependency-injected version of the [async.auto]{@link module:ControlFlow.auto} function. Dependent
+ * tasks are specified as parameters to the function, after the usual callback
+ * parameter, with the parameter names matching the names of the tasks it
+ * depends on. This can provide even more readable task graphs which can be
+ * easier to maintain.
+ *
+ * If a final callback is specified, the task results are similarly injected,
+ * specified as named parameters after the initial error parameter.
+ *
+ * The autoInject function is purely syntactic sugar and its semantics are
+ * otherwise equivalent to [async.auto]{@link module:ControlFlow.auto}.
+ *
+ * @name autoInject
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.auto]{@link module:ControlFlow.auto}
+ * @category Control Flow
+ * @param {Object} tasks - An object, each of whose properties is an {@link AsyncFunction} of
+ * the form 'func([dependencies...], callback). The object's key of a property
+ * serves as the name of the task defined by that property, i.e. can be used
+ * when specifying requirements for other tasks.
+ * * The `callback` parameter is a `callback(err, result)` which must be called
+ *   when finished, passing an `error` (which can be `null`) and the result of
+ *   the function's execution. The remaining parameters name other tasks on
+ *   which the task is dependent, and the results from those tasks are the
+ *   arguments of those parameters.
+ * @param {Function} [callback] - An optional callback which is called when all
+ * the tasks have been completed. It receives the `err` argument if any `tasks`
+ * pass an error to their callback, and a `results` object with any completed
+ * task results, similar to `auto`.
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * //  The example from `auto` can be rewritten as follows:
+ * async.autoInject({
+ *     get_data: function(callback) {
+ *         // async code to get some data
+ *         callback(null, 'data', 'converted to array');
+ *     },
+ *     make_folder: function(callback) {
+ *         // async code to create a directory to store a file in
+ *         // this is run at the same time as getting the data
+ *         callback(null, 'folder');
+ *     },
+ *     write_file: function(get_data, make_folder, callback) {
+ *         // once there is some data and the directory exists,
+ *         // write the data to a file in the directory
+ *         callback(null, 'filename');
+ *     },
+ *     email_link: function(write_file, callback) {
+ *         // once the file is written let's email a link to it...
+ *         // write_file contains the filename returned by write_file.
+ *         callback(null, {'file':write_file, 'email':'user@example.com'});
+ *     }
+ * }, function(err, results) {
+ *     console.log('err = ', err);
+ *     console.log('email_link = ', results.email_link);
+ * });
+ *
+ * // If you are using a JS minifier that mangles parameter names, `autoInject`
+ * // will not work with plain functions, since the parameter names will be
+ * // collapsed to a single letter identifier.  To work around this, you can
+ * // explicitly specify the names of the parameters your task function needs
+ * // in an array, similar to Angular.js dependency injection.
+ *
+ * // This still has an advantage over plain `auto`, since the results a task
+ * // depends on are still spread into arguments.
+ * async.autoInject({
+ *     //...
+ *     write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) {
+ *         callback(null, 'filename');
+ *     }],
+ *     email_link: ['write_file', function(write_file, callback) {
+ *         callback(null, {'file':write_file, 'email':'user@example.com'});
+ *     }]
+ *     //...
+ * }, function(err, results) {
+ *     console.log('err = ', err);
+ *     console.log('email_link = ', results.email_link);
+ * });
+ */
+function autoInject(tasks, callback) {
+    var newTasks = {};
+
+    Object.keys(tasks).forEach(key => {
+        var taskFn = tasks[key];
+        var params;
+        var fnIsAsync = (0, _wrapAsync.isAsync)(taskFn);
+        var hasNoDeps = !fnIsAsync && taskFn.length === 1 || fnIsAsync && taskFn.length === 0;
+
+        if (Array.isArray(taskFn)) {
+            params = [...taskFn];
+            taskFn = params.pop();
+
+            newTasks[key] = params.concat(params.length > 0 ? newTask : taskFn);
+        } else if (hasNoDeps) {
+            // no dependencies, use the function as-is
+            newTasks[key] = taskFn;
+        } else {
+            params = parseParams(taskFn);
+            if (taskFn.length === 0 && !fnIsAsync && params.length === 0) {
+                throw new Error("autoInject task functions require explicit parameters.");
+            }
+
+            // remove callback param
+            if (!fnIsAsync) params.pop();
+
+            newTasks[key] = params.concat(newTask);
+        }
+
+        function newTask(results, taskCb) {
+            var newArgs = params.map(name => results[name]);
+            newArgs.push(taskCb);
+            (0, _wrapAsync2.default)(taskFn)(...newArgs);
+        }
+    });
+
+    return (0, _auto2.default)(newTasks, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/bower.json b/node_modules/async/bower.json
index 18176881e0075ffcd0ad3734cf1af6c80349b917..390c6502f581075c067713444865d08b81a8bbd5 100644
--- a/node_modules/async/bower.json
+++ b/node_modules/async/bower.json
@@ -1,38 +1,17 @@
 {
   "name": "async",
-  "description": "Higher-order functions and common patterns for asynchronous code",
-  "version": "0.9.2",
-  "main": "lib/async.js",
-  "keywords": [
-    "async",
-    "callback",
-    "utility",
-    "module"
-  ],
-  "license": "MIT",
-  "repository": {
-    "type": "git",
-    "url": "https://github.com/caolan/async.git"
-  },
-  "devDependencies": {
-    "nodeunit": ">0.0.0",
-    "uglify-js": "1.2.x",
-    "nodelint": ">0.0.0",
-    "lodash": ">=2.4.1"
-  },
-  "moduleType": [
-    "amd",
-    "globals",
-    "node"
-  ],
+  "main": "dist/async.js",
   "ignore": [
-    "**/.*",
-    "node_modules",
     "bower_components",
+    "lib",
     "test",
-    "tests"
-  ],
-  "authors": [
-    "Caolan McMahon"
+    "node_modules",
+    "perf",
+    "support",
+    "**/.*",
+    "*.config.js",
+    "*.json",
+    "index.js",
+    "Makefile"
   ]
-}
\ No newline at end of file
+}
diff --git a/node_modules/async/cargo.js b/node_modules/async/cargo.js
new file mode 100644
index 0000000000000000000000000000000000000000..aa385f8a8ad674973035059885b5c53692ff4081
--- /dev/null
+++ b/node_modules/async/cargo.js
@@ -0,0 +1,63 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = cargo;
+
+var _queue = require('./internal/queue.js');
+
+var _queue2 = _interopRequireDefault(_queue);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Creates a `cargo` object with the specified payload. Tasks added to the
+ * cargo will be processed altogether (up to the `payload` limit). If the
+ * `worker` is in progress, the task is queued until it becomes available. Once
+ * the `worker` has completed some tasks, each callback of those tasks is
+ * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966)
+ * for how `cargo` and `queue` work.
+ *
+ * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers
+ * at a time, cargo passes an array of tasks to a single worker, repeating
+ * when the worker is finished.
+ *
+ * @name cargo
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.queue]{@link module:ControlFlow.queue}
+ * @category Control Flow
+ * @param {AsyncFunction} worker - An asynchronous function for processing an array
+ * of queued tasks. Invoked with `(tasks, callback)`.
+ * @param {number} [payload=Infinity] - An optional `integer` for determining
+ * how many tasks should be processed per round; if omitted, the default is
+ * unlimited.
+ * @returns {module:ControlFlow.QueueObject} A cargo object to manage the tasks. Callbacks can
+ * attached as certain properties to listen for specific events during the
+ * lifecycle of the cargo and inner queue.
+ * @example
+ *
+ * // create a cargo object with payload 2
+ * var cargo = async.cargo(function(tasks, callback) {
+ *     for (var i=0; i<tasks.length; i++) {
+ *         console.log('hello ' + tasks[i].name);
+ *     }
+ *     callback();
+ * }, 2);
+ *
+ * // add some items
+ * cargo.push({name: 'foo'}, function(err) {
+ *     console.log('finished processing foo');
+ * });
+ * cargo.push({name: 'bar'}, function(err) {
+ *     console.log('finished processing bar');
+ * });
+ * await cargo.push({name: 'baz'});
+ * console.log('finished processing baz');
+ */
+function cargo(worker, payload) {
+  return (0, _queue2.default)(worker, 1, payload);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/cargoQueue.js b/node_modules/async/cargoQueue.js
new file mode 100644
index 0000000000000000000000000000000000000000..823a63144f7f3bd7d5de26c3aaf0cd0100e6a571
--- /dev/null
+++ b/node_modules/async/cargoQueue.js
@@ -0,0 +1,71 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = cargo;
+
+var _queue = require('./internal/queue.js');
+
+var _queue2 = _interopRequireDefault(_queue);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Creates a `cargoQueue` object with the specified payload. Tasks added to the
+ * cargoQueue will be processed together (up to the `payload` limit) in `concurrency` parallel workers.
+ * If the all `workers` are in progress, the task is queued until one becomes available. Once
+ * a `worker` has completed some tasks, each callback of those tasks is
+ * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966)
+ * for how `cargo` and `queue` work.
+ *
+ * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers
+ * at a time, and [`cargo`]{@link module:ControlFlow.cargo} passes an array of tasks to a single worker,
+ * the cargoQueue passes an array of tasks to multiple parallel workers.
+ *
+ * @name cargoQueue
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.queue]{@link module:ControlFlow.queue}
+ * @see [async.cargo]{@link module:ControlFLow.cargo}
+ * @category Control Flow
+ * @param {AsyncFunction} worker - An asynchronous function for processing an array
+ * of queued tasks. Invoked with `(tasks, callback)`.
+ * @param {number} [concurrency=1] - An `integer` for determining how many
+ * `worker` functions should be run in parallel.  If omitted, the concurrency
+ * defaults to `1`.  If the concurrency is `0`, an error is thrown.
+ * @param {number} [payload=Infinity] - An optional `integer` for determining
+ * how many tasks should be processed per round; if omitted, the default is
+ * unlimited.
+ * @returns {module:ControlFlow.QueueObject} A cargoQueue object to manage the tasks. Callbacks can
+ * attached as certain properties to listen for specific events during the
+ * lifecycle of the cargoQueue and inner queue.
+ * @example
+ *
+ * // create a cargoQueue object with payload 2 and concurrency 2
+ * var cargoQueue = async.cargoQueue(function(tasks, callback) {
+ *     for (var i=0; i<tasks.length; i++) {
+ *         console.log('hello ' + tasks[i].name);
+ *     }
+ *     callback();
+ * }, 2, 2);
+ *
+ * // add some items
+ * cargoQueue.push({name: 'foo'}, function(err) {
+ *     console.log('finished processing foo');
+ * });
+ * cargoQueue.push({name: 'bar'}, function(err) {
+ *     console.log('finished processing bar');
+ * });
+ * cargoQueue.push({name: 'baz'}, function(err) {
+ *     console.log('finished processing baz');
+ * });
+ * cargoQueue.push({name: 'boo'}, function(err) {
+ *     console.log('finished processing boo');
+ * });
+ */
+function cargo(worker, concurrency, payload) {
+  return (0, _queue2.default)(worker, concurrency, payload);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/component.json b/node_modules/async/component.json
deleted file mode 100644
index 5003a7c52ce7fdfb3710e27c9b27e70da0df92e4..0000000000000000000000000000000000000000
--- a/node_modules/async/component.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-  "name": "async",
-  "description": "Higher-order functions and common patterns for asynchronous code",
-  "version": "0.9.2",
-  "keywords": [
-    "async",
-    "callback",
-    "utility",
-    "module"
-  ],
-  "license": "MIT",
-  "repository": "caolan/async",
-  "scripts": [
-    "lib/async.js"
-  ]
-}
\ No newline at end of file
diff --git a/node_modules/async/compose.js b/node_modules/async/compose.js
new file mode 100644
index 0000000000000000000000000000000000000000..d4ce989328cf662b21d003b0eb42229b28f25e9a
--- /dev/null
+++ b/node_modules/async/compose.js
@@ -0,0 +1,55 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = compose;
+
+var _seq = require('./seq.js');
+
+var _seq2 = _interopRequireDefault(_seq);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Creates a function which is a composition of the passed asynchronous
+ * functions. Each function consumes the return value of the function that
+ * follows. Composing functions `f()`, `g()`, and `h()` would produce the result
+ * of `f(g(h()))`, only this version uses callbacks to obtain the return values.
+ *
+ * If the last argument to the composed function is not a function, a promise
+ * is returned when you call it.
+ *
+ * Each function is executed with the `this` binding of the composed function.
+ *
+ * @name compose
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {...AsyncFunction} functions - the asynchronous functions to compose
+ * @returns {Function} an asynchronous function that is the composed
+ * asynchronous `functions`
+ * @example
+ *
+ * function add1(n, callback) {
+ *     setTimeout(function () {
+ *         callback(null, n + 1);
+ *     }, 10);
+ * }
+ *
+ * function mul3(n, callback) {
+ *     setTimeout(function () {
+ *         callback(null, n * 3);
+ *     }, 10);
+ * }
+ *
+ * var add1mul3 = async.compose(mul3, add1);
+ * add1mul3(4, function (err, result) {
+ *     // result now equals 15
+ * });
+ */
+function compose(...args) {
+  return (0, _seq2.default)(...args.reverse());
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/concat.js b/node_modules/async/concat.js
new file mode 100644
index 0000000000000000000000000000000000000000..8eed1ac899d83824494757845c34709435327129
--- /dev/null
+++ b/node_modules/async/concat.js
@@ -0,0 +1,115 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _concatLimit = require('./concatLimit.js');
+
+var _concatLimit2 = _interopRequireDefault(_concatLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Applies `iteratee` to each item in `coll`, concatenating the results. Returns
+ * the concatenated list. The `iteratee`s are called in parallel, and the
+ * results are concatenated as they return. The results array will be returned in
+ * the original order of `coll` passed to the `iteratee` function.
+ *
+ * @name concat
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @alias flatMap
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
+ * which should use an array as its result. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is an array
+ * containing the concatenated results of the `iteratee` function. Invoked with
+ * (err, results).
+ * @returns A Promise, if no callback is passed
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * let directoryList = ['dir1','dir2','dir3'];
+ * let withMissingDirectoryList = ['dir1','dir2','dir3', 'dir4'];
+ *
+ * // Using callbacks
+ * async.concat(directoryList, fs.readdir, function(err, results) {
+ *    if (err) {
+ *        console.log(err);
+ *    } else {
+ *        console.log(results);
+ *        // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+ *    }
+ * });
+ *
+ * // Error Handling
+ * async.concat(withMissingDirectoryList, fs.readdir, function(err, results) {
+ *    if (err) {
+ *        console.log(err);
+ *        // [ Error: ENOENT: no such file or directory ]
+ *        // since dir4 does not exist
+ *    } else {
+ *        console.log(results);
+ *    }
+ * });
+ *
+ * // Using Promises
+ * async.concat(directoryList, fs.readdir)
+ * .then(results => {
+ *     console.log(results);
+ *     // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+ * }).catch(err => {
+ *      console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.concat(withMissingDirectoryList, fs.readdir)
+ * .then(results => {
+ *     console.log(results);
+ * }).catch(err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ *     // since dir4 does not exist
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.concat(directoryList, fs.readdir);
+ *         console.log(results);
+ *         // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+ *     } catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let results = await async.concat(withMissingDirectoryList, fs.readdir);
+ *         console.log(results);
+ *     } catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *         // since dir4 does not exist
+ *     }
+ * }
+ *
+ */
+function concat(coll, iteratee, callback) {
+  return (0, _concatLimit2.default)(coll, Infinity, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(concat, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/concatLimit.js b/node_modules/async/concatLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..3d170f1770bdb2b8a96ae9928991e6fda027a1f4
--- /dev/null
+++ b/node_modules/async/concatLimit.js
@@ -0,0 +1,60 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _mapLimit = require('./mapLimit.js');
+
+var _mapLimit2 = _interopRequireDefault(_mapLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name concatLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.concat]{@link module:Collections.concat}
+ * @category Collection
+ * @alias flatMapLimit
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
+ * which should use an array as its result. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is an array
+ * containing the concatenated results of the `iteratee` function. Invoked with
+ * (err, results).
+ * @returns A Promise, if no callback is passed
+ */
+function concatLimit(coll, limit, iteratee, callback) {
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+    return (0, _mapLimit2.default)(coll, limit, (val, iterCb) => {
+        _iteratee(val, (err, ...args) => {
+            if (err) return iterCb(err);
+            return iterCb(err, args);
+        });
+    }, (err, mapResults) => {
+        var result = [];
+        for (var i = 0; i < mapResults.length; i++) {
+            if (mapResults[i]) {
+                result = result.concat(...mapResults[i]);
+            }
+        }
+
+        return callback(err, result);
+    });
+}
+exports.default = (0, _awaitify2.default)(concatLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/concatSeries.js b/node_modules/async/concatSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..84add3b0651afe444b06cdcb56d8cc1d56c39fb4
--- /dev/null
+++ b/node_modules/async/concatSeries.js
@@ -0,0 +1,41 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _concatLimit = require('./concatLimit.js');
+
+var _concatLimit2 = _interopRequireDefault(_concatLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time.
+ *
+ * @name concatSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.concat]{@link module:Collections.concat}
+ * @category Collection
+ * @alias flatMapSeries
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`.
+ * The iteratee should complete with an array an array of results.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is an array
+ * containing the concatenated results of the `iteratee` function. Invoked with
+ * (err, results).
+ * @returns A Promise, if no callback is passed
+ */
+function concatSeries(coll, iteratee, callback) {
+  return (0, _concatLimit2.default)(coll, 1, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(concatSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/constant.js b/node_modules/async/constant.js
new file mode 100644
index 0000000000000000000000000000000000000000..07596538c681a301d676ff06acbe28371f50ed1c
--- /dev/null
+++ b/node_modules/async/constant.js
@@ -0,0 +1,55 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+exports.default = function (...args) {
+    return function (...ignoredArgs /*, callback*/) {
+        var callback = ignoredArgs.pop();
+        return callback(null, ...args);
+    };
+};
+
+module.exports = exports["default"]; /**
+                                      * Returns a function that when called, calls-back with the values provided.
+                                      * Useful as the first function in a [`waterfall`]{@link module:ControlFlow.waterfall}, or for plugging values in to
+                                      * [`auto`]{@link module:ControlFlow.auto}.
+                                      *
+                                      * @name constant
+                                      * @static
+                                      * @memberOf module:Utils
+                                      * @method
+                                      * @category Util
+                                      * @param {...*} arguments... - Any number of arguments to automatically invoke
+                                      * callback with.
+                                      * @returns {AsyncFunction} Returns a function that when invoked, automatically
+                                      * invokes the callback with the previous given arguments.
+                                      * @example
+                                      *
+                                      * async.waterfall([
+                                      *     async.constant(42),
+                                      *     function (value, next) {
+                                      *         // value === 42
+                                      *     },
+                                      *     //...
+                                      * ], callback);
+                                      *
+                                      * async.waterfall([
+                                      *     async.constant(filename, "utf8"),
+                                      *     fs.readFile,
+                                      *     function (fileData, next) {
+                                      *         //...
+                                      *     }
+                                      *     //...
+                                      * ], callback);
+                                      *
+                                      * async.auto({
+                                      *     hostname: async.constant("https://server.net/"),
+                                      *     port: findFreePort,
+                                      *     launchServer: ["hostname", "port", function (options, cb) {
+                                      *         startServer(options, cb);
+                                      *     }],
+                                      *     //...
+                                      * }, callback);
+                                      */
\ No newline at end of file
diff --git a/node_modules/async/detect.js b/node_modules/async/detect.js
new file mode 100644
index 0000000000000000000000000000000000000000..05b2e5c60fff46fa850597e99992c0094eb8a458
--- /dev/null
+++ b/node_modules/async/detect.js
@@ -0,0 +1,96 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Returns the first value in `coll` that passes an async truth test. The
+ * `iteratee` is applied in parallel, meaning the first iteratee to return
+ * `true` will fire the detect `callback` with that result. That means the
+ * result might not be the first item in the original `coll` (in terms of order)
+ * that passes the test.
+
+ * If order within the original `coll` is important, then look at
+ * [`detectSeries`]{@link module:Collections.detectSeries}.
+ *
+ * @name detect
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias find
+ * @category Collections
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+ * The iteratee must complete with a boolean value as its result.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the `iteratee` functions have finished.
+ * Result will be the first item in the array that passes the truth test
+ * (iteratee) or the value `undefined` if none passed. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists,
+ *    function(err, result) {
+ *        console.log(result);
+ *        // dir1/file1.txt
+ *        // result now equals the first file in the list that exists
+ *    }
+ *);
+ *
+ * // Using Promises
+ * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists)
+ * .then(result => {
+ *     console.log(result);
+ *     // dir1/file1.txt
+ *     // result now equals the first file in the list that exists
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists);
+ *         console.log(result);
+ *         // dir1/file1.txt
+ *         // result now equals the file in the list that exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function detect(coll, iteratee, callback) {
+  return (0, _createTester2.default)(bool => bool, (res, item) => item)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(detect, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/detectLimit.js b/node_modules/async/detectLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..db6961ec5e0bd8be5038278b8245af429125b3fb
--- /dev/null
+++ b/node_modules/async/detectLimit.js
@@ -0,0 +1,48 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name detectLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.detect]{@link module:Collections.detect}
+ * @alias findLimit
+ * @category Collections
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+ * The iteratee must complete with a boolean value as its result.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the `iteratee` functions have finished.
+ * Result will be the first item in the array that passes the truth test
+ * (iteratee) or the value `undefined` if none passed. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function detectLimit(coll, limit, iteratee, callback) {
+  return (0, _createTester2.default)(bool => bool, (res, item) => item)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(detectLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/detectSeries.js b/node_modules/async/detectSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..b9131b4a3c5d65c58c0c4743f1845293823787f9
--- /dev/null
+++ b/node_modules/async/detectSeries.js
@@ -0,0 +1,47 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time.
+ *
+ * @name detectSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.detect]{@link module:Collections.detect}
+ * @alias findSeries
+ * @category Collections
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+ * The iteratee must complete with a boolean value as its result.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the `iteratee` functions have finished.
+ * Result will be the first item in the array that passes the truth test
+ * (iteratee) or the value `undefined` if none passed. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function detectSeries(coll, iteratee, callback) {
+  return (0, _createTester2.default)(bool => bool, (res, item) => item)((0, _eachOfLimit2.default)(1), coll, iteratee, callback);
+}
+
+exports.default = (0, _awaitify2.default)(detectSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/dir.js b/node_modules/async/dir.js
new file mode 100644
index 0000000000000000000000000000000000000000..950d0a22e617e316390ae9c368c79500d8636d1d
--- /dev/null
+++ b/node_modules/async/dir.js
@@ -0,0 +1,43 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _consoleFunc = require('./internal/consoleFunc.js');
+
+var _consoleFunc2 = _interopRequireDefault(_consoleFunc);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Logs the result of an [`async` function]{@link AsyncFunction} to the
+ * `console` using `console.dir` to display the properties of the resulting object.
+ * Only works in Node.js or in browsers that support `console.dir` and
+ * `console.error` (such as FF and Chrome).
+ * If multiple arguments are returned from the async function,
+ * `console.dir` is called on each argument in order.
+ *
+ * @name dir
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} function - The function you want to eventually apply
+ * all arguments to.
+ * @param {...*} arguments... - Any number of arguments to apply to the function.
+ * @example
+ *
+ * // in a module
+ * var hello = function(name, callback) {
+ *     setTimeout(function() {
+ *         callback(null, {hello: name});
+ *     }, 1000);
+ * };
+ *
+ * // in the node repl
+ * node> async.dir(hello, 'world');
+ * {hello: 'world'}
+ */
+exports.default = (0, _consoleFunc2.default)('dir');
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/dist/async.js b/node_modules/async/dist/async.js
new file mode 100644
index 0000000000000000000000000000000000000000..8d5e782564510c2c3093dd1a37b629cfa55c5256
--- /dev/null
+++ b/node_modules/async/dist/async.js
@@ -0,0 +1,6059 @@
+(function (global, factory) {
+    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+    typeof define === 'function' && define.amd ? define(['exports'], factory) :
+    (factory((global.async = {})));
+}(this, (function (exports) { 'use strict';
+
+    /**
+     * Creates a continuation function with some arguments already applied.
+     *
+     * Useful as a shorthand when combined with other control flow functions. Any
+     * arguments passed to the returned function are added to the arguments
+     * originally passed to apply.
+     *
+     * @name apply
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @category Util
+     * @param {Function} fn - The function you want to eventually apply all
+     * arguments to. Invokes with (arguments...).
+     * @param {...*} arguments... - Any number of arguments to automatically apply
+     * when the continuation is called.
+     * @returns {Function} the partially-applied function
+     * @example
+     *
+     * // using apply
+     * async.parallel([
+     *     async.apply(fs.writeFile, 'testfile1', 'test1'),
+     *     async.apply(fs.writeFile, 'testfile2', 'test2')
+     * ]);
+     *
+     *
+     * // the same process without using apply
+     * async.parallel([
+     *     function(callback) {
+     *         fs.writeFile('testfile1', 'test1', callback);
+     *     },
+     *     function(callback) {
+     *         fs.writeFile('testfile2', 'test2', callback);
+     *     }
+     * ]);
+     *
+     * // It's possible to pass any number of additional arguments when calling the
+     * // continuation:
+     *
+     * node> var fn = async.apply(sys.puts, 'one');
+     * node> fn('two', 'three');
+     * one
+     * two
+     * three
+     */
+    function apply(fn, ...args) {
+        return (...callArgs) => fn(...args,...callArgs);
+    }
+
+    function initialParams (fn) {
+        return function (...args/*, callback*/) {
+            var callback = args.pop();
+            return fn.call(this, args, callback);
+        };
+    }
+
+    /* istanbul ignore file */
+
+    var hasQueueMicrotask = typeof queueMicrotask === 'function' && queueMicrotask;
+    var hasSetImmediate = typeof setImmediate === 'function' && setImmediate;
+    var hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function';
+
+    function fallback(fn) {
+        setTimeout(fn, 0);
+    }
+
+    function wrap(defer) {
+        return (fn, ...args) => defer(() => fn(...args));
+    }
+
+    var _defer;
+
+    if (hasQueueMicrotask) {
+        _defer = queueMicrotask;
+    } else if (hasSetImmediate) {
+        _defer = setImmediate;
+    } else if (hasNextTick) {
+        _defer = process.nextTick;
+    } else {
+        _defer = fallback;
+    }
+
+    var setImmediate$1 = wrap(_defer);
+
+    /**
+     * Take a sync function and make it async, passing its return value to a
+     * callback. This is useful for plugging sync functions into a waterfall,
+     * series, or other async functions. Any arguments passed to the generated
+     * function will be passed to the wrapped function (except for the final
+     * callback argument). Errors thrown will be passed to the callback.
+     *
+     * If the function passed to `asyncify` returns a Promise, that promises's
+     * resolved/rejected state will be used to call the callback, rather than simply
+     * the synchronous return value.
+     *
+     * This also means you can asyncify ES2017 `async` functions.
+     *
+     * @name asyncify
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @alias wrapSync
+     * @category Util
+     * @param {Function} func - The synchronous function, or Promise-returning
+     * function to convert to an {@link AsyncFunction}.
+     * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be
+     * invoked with `(args..., callback)`.
+     * @example
+     *
+     * // passing a regular synchronous function
+     * async.waterfall([
+     *     async.apply(fs.readFile, filename, "utf8"),
+     *     async.asyncify(JSON.parse),
+     *     function (data, next) {
+     *         // data is the result of parsing the text.
+     *         // If there was a parsing error, it would have been caught.
+     *     }
+     * ], callback);
+     *
+     * // passing a function returning a promise
+     * async.waterfall([
+     *     async.apply(fs.readFile, filename, "utf8"),
+     *     async.asyncify(function (contents) {
+     *         return db.model.create(contents);
+     *     }),
+     *     function (model, next) {
+     *         // `model` is the instantiated model object.
+     *         // If there was an error, this function would be skipped.
+     *     }
+     * ], callback);
+     *
+     * // es2017 example, though `asyncify` is not needed if your JS environment
+     * // supports async functions out of the box
+     * var q = async.queue(async.asyncify(async function(file) {
+     *     var intermediateStep = await processFile(file);
+     *     return await somePromise(intermediateStep)
+     * }));
+     *
+     * q.push(files);
+     */
+    function asyncify(func) {
+        if (isAsync(func)) {
+            return function (...args/*, callback*/) {
+                const callback = args.pop();
+                const promise = func.apply(this, args);
+                return handlePromise(promise, callback)
+            }
+        }
+
+        return initialParams(function (args, callback) {
+            var result;
+            try {
+                result = func.apply(this, args);
+            } catch (e) {
+                return callback(e);
+            }
+            // if result is Promise object
+            if (result && typeof result.then === 'function') {
+                return handlePromise(result, callback)
+            } else {
+                callback(null, result);
+            }
+        });
+    }
+
+    function handlePromise(promise, callback) {
+        return promise.then(value => {
+            invokeCallback(callback, null, value);
+        }, err => {
+            invokeCallback(callback, err && err.message ? err : new Error(err));
+        });
+    }
+
+    function invokeCallback(callback, error, value) {
+        try {
+            callback(error, value);
+        } catch (err) {
+            setImmediate$1(e => { throw e }, err);
+        }
+    }
+
+    function isAsync(fn) {
+        return fn[Symbol.toStringTag] === 'AsyncFunction';
+    }
+
+    function isAsyncGenerator(fn) {
+        return fn[Symbol.toStringTag] === 'AsyncGenerator';
+    }
+
+    function isAsyncIterable(obj) {
+        return typeof obj[Symbol.asyncIterator] === 'function';
+    }
+
+    function wrapAsync(asyncFn) {
+        if (typeof asyncFn !== 'function') throw new Error('expected a function')
+        return isAsync(asyncFn) ? asyncify(asyncFn) : asyncFn;
+    }
+
+    // conditionally promisify a function.
+    // only return a promise if a callback is omitted
+    function awaitify (asyncFn, arity = asyncFn.length) {
+        if (!arity) throw new Error('arity is undefined')
+        function awaitable (...args) {
+            if (typeof args[arity - 1] === 'function') {
+                return asyncFn.apply(this, args)
+            }
+
+            return new Promise((resolve, reject) => {
+                args[arity - 1] = (err, ...cbArgs) => {
+                    if (err) return reject(err)
+                    resolve(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
+                };
+                asyncFn.apply(this, args);
+            })
+        }
+
+        return awaitable
+    }
+
+    function applyEach (eachfn) {
+        return function applyEach(fns, ...callArgs) {
+            const go = awaitify(function (callback) {
+                var that = this;
+                return eachfn(fns, (fn, cb) => {
+                    wrapAsync(fn).apply(that, callArgs.concat(cb));
+                }, callback);
+            });
+            return go;
+        };
+    }
+
+    function _asyncMap(eachfn, arr, iteratee, callback) {
+        arr = arr || [];
+        var results = [];
+        var counter = 0;
+        var _iteratee = wrapAsync(iteratee);
+
+        return eachfn(arr, (value, _, iterCb) => {
+            var index = counter++;
+            _iteratee(value, (err, v) => {
+                results[index] = v;
+                iterCb(err);
+            });
+        }, err => {
+            callback(err, results);
+        });
+    }
+
+    function isArrayLike(value) {
+        return value &&
+            typeof value.length === 'number' &&
+            value.length >= 0 &&
+            value.length % 1 === 0;
+    }
+
+    // A temporary value used to identify if the loop should be broken.
+    // See #1064, #1293
+    const breakLoop = {};
+
+    function once(fn) {
+        function wrapper (...args) {
+            if (fn === null) return;
+            var callFn = fn;
+            fn = null;
+            callFn.apply(this, args);
+        }
+        Object.assign(wrapper, fn);
+        return wrapper
+    }
+
+    function getIterator (coll) {
+        return coll[Symbol.iterator] && coll[Symbol.iterator]();
+    }
+
+    function createArrayIterator(coll) {
+        var i = -1;
+        var len = coll.length;
+        return function next() {
+            return ++i < len ? {value: coll[i], key: i} : null;
+        }
+    }
+
+    function createES2015Iterator(iterator) {
+        var i = -1;
+        return function next() {
+            var item = iterator.next();
+            if (item.done)
+                return null;
+            i++;
+            return {value: item.value, key: i};
+        }
+    }
+
+    function createObjectIterator(obj) {
+        var okeys = obj ? Object.keys(obj) : [];
+        var i = -1;
+        var len = okeys.length;
+        return function next() {
+            var key = okeys[++i];
+            if (key === '__proto__') {
+                return next();
+            }
+            return i < len ? {value: obj[key], key} : null;
+        };
+    }
+
+    function createIterator(coll) {
+        if (isArrayLike(coll)) {
+            return createArrayIterator(coll);
+        }
+
+        var iterator = getIterator(coll);
+        return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll);
+    }
+
+    function onlyOnce(fn) {
+        return function (...args) {
+            if (fn === null) throw new Error("Callback was already called.");
+            var callFn = fn;
+            fn = null;
+            callFn.apply(this, args);
+        };
+    }
+
+    // for async generators
+    function asyncEachOfLimit(generator, limit, iteratee, callback) {
+        let done = false;
+        let canceled = false;
+        let awaiting = false;
+        let running = 0;
+        let idx = 0;
+
+        function replenish() {
+            //console.log('replenish')
+            if (running >= limit || awaiting || done) return
+            //console.log('replenish awaiting')
+            awaiting = true;
+            generator.next().then(({value, done: iterDone}) => {
+                //console.log('got value', value)
+                if (canceled || done) return
+                awaiting = false;
+                if (iterDone) {
+                    done = true;
+                    if (running <= 0) {
+                        //console.log('done nextCb')
+                        callback(null);
+                    }
+                    return;
+                }
+                running++;
+                iteratee(value, idx, iterateeCallback);
+                idx++;
+                replenish();
+            }).catch(handleError);
+        }
+
+        function iterateeCallback(err, result) {
+            //console.log('iterateeCallback')
+            running -= 1;
+            if (canceled) return
+            if (err) return handleError(err)
+
+            if (err === false) {
+                done = true;
+                canceled = true;
+                return
+            }
+
+            if (result === breakLoop || (done && running <= 0)) {
+                done = true;
+                //console.log('done iterCb')
+                return callback(null);
+            }
+            replenish();
+        }
+
+        function handleError(err) {
+            if (canceled) return
+            awaiting = false;
+            done = true;
+            callback(err);
+        }
+
+        replenish();
+    }
+
+    var eachOfLimit = (limit) => {
+        return (obj, iteratee, callback) => {
+            callback = once(callback);
+            if (limit <= 0) {
+                throw new RangeError('concurrency limit cannot be less than 1')
+            }
+            if (!obj) {
+                return callback(null);
+            }
+            if (isAsyncGenerator(obj)) {
+                return asyncEachOfLimit(obj, limit, iteratee, callback)
+            }
+            if (isAsyncIterable(obj)) {
+                return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback)
+            }
+            var nextElem = createIterator(obj);
+            var done = false;
+            var canceled = false;
+            var running = 0;
+            var looping = false;
+
+            function iterateeCallback(err, value) {
+                if (canceled) return
+                running -= 1;
+                if (err) {
+                    done = true;
+                    callback(err);
+                }
+                else if (err === false) {
+                    done = true;
+                    canceled = true;
+                }
+                else if (value === breakLoop || (done && running <= 0)) {
+                    done = true;
+                    return callback(null);
+                }
+                else if (!looping) {
+                    replenish();
+                }
+            }
+
+            function replenish () {
+                looping = true;
+                while (running < limit && !done) {
+                    var elem = nextElem();
+                    if (elem === null) {
+                        done = true;
+                        if (running <= 0) {
+                            callback(null);
+                        }
+                        return;
+                    }
+                    running += 1;
+                    iteratee(elem.value, elem.key, onlyOnce(iterateeCallback));
+                }
+                looping = false;
+            }
+
+            replenish();
+        };
+    };
+
+    /**
+     * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a
+     * time.
+     *
+     * @name eachOfLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.eachOf]{@link module:Collections.eachOf}
+     * @alias forEachOfLimit
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - An async function to apply to each
+     * item in `coll`. The `key` is the item's key, or index in the case of an
+     * array.
+     * Invoked with (item, key, callback).
+     * @param {Function} [callback] - A callback which is called when all
+     * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+     * @returns {Promise} a promise, if a callback is omitted
+     */
+    function eachOfLimit$1(coll, limit, iteratee, callback) {
+        return eachOfLimit(limit)(coll, wrapAsync(iteratee), callback);
+    }
+
+    var eachOfLimit$2 = awaitify(eachOfLimit$1, 4);
+
+    // eachOf implementation optimized for array-likes
+    function eachOfArrayLike(coll, iteratee, callback) {
+        callback = once(callback);
+        var index = 0,
+            completed = 0,
+            {length} = coll,
+            canceled = false;
+        if (length === 0) {
+            callback(null);
+        }
+
+        function iteratorCallback(err, value) {
+            if (err === false) {
+                canceled = true;
+            }
+            if (canceled === true) return
+            if (err) {
+                callback(err);
+            } else if ((++completed === length) || value === breakLoop) {
+                callback(null);
+            }
+        }
+
+        for (; index < length; index++) {
+            iteratee(coll[index], index, onlyOnce(iteratorCallback));
+        }
+    }
+
+    // a generic version of eachOf which can handle array, object, and iterator cases.
+    function eachOfGeneric (coll, iteratee, callback) {
+        return eachOfLimit$2(coll, Infinity, iteratee, callback);
+    }
+
+    /**
+     * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument
+     * to the iteratee.
+     *
+     * @name eachOf
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @alias forEachOf
+     * @category Collection
+     * @see [async.each]{@link module:Collections.each}
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - A function to apply to each
+     * item in `coll`.
+     * The `key` is the item's key, or index in the case of an array.
+     * Invoked with (item, key, callback).
+     * @param {Function} [callback] - A callback which is called when all
+     * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+     * @returns {Promise} a promise, if a callback is omitted
+     * @example
+     *
+     * // dev.json is a file containing a valid json object config for dev environment
+     * // dev.json is a file containing a valid json object config for test environment
+     * // prod.json is a file containing a valid json object config for prod environment
+     * // invalid.json is a file with a malformed json object
+     *
+     * let configs = {}; //global variable
+     * let validConfigFileMap = {dev: 'dev.json', test: 'test.json', prod: 'prod.json'};
+     * let invalidConfigFileMap = {dev: 'dev.json', test: 'test.json', invalid: 'invalid.json'};
+     *
+     * // asynchronous function that reads a json file and parses the contents as json object
+     * function parseFile(file, key, callback) {
+     *     fs.readFile(file, "utf8", function(err, data) {
+     *         if (err) return calback(err);
+     *         try {
+     *             configs[key] = JSON.parse(data);
+     *         } catch (e) {
+     *             return callback(e);
+     *         }
+     *         callback();
+     *     });
+     * }
+     *
+     * // Using callbacks
+     * async.forEachOf(validConfigFileMap, parseFile, function (err) {
+     *     if (err) {
+     *         console.error(err);
+     *     } else {
+     *         console.log(configs);
+     *         // configs is now a map of JSON data, e.g.
+     *         // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+     *     }
+     * });
+     *
+     * //Error handing
+     * async.forEachOf(invalidConfigFileMap, parseFile, function (err) {
+     *     if (err) {
+     *         console.error(err);
+     *         // JSON parse error exception
+     *     } else {
+     *         console.log(configs);
+     *     }
+     * });
+     *
+     * // Using Promises
+     * async.forEachOf(validConfigFileMap, parseFile)
+     * .then( () => {
+     *     console.log(configs);
+     *     // configs is now a map of JSON data, e.g.
+     *     // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+     * }).catch( err => {
+     *     console.error(err);
+     * });
+     *
+     * //Error handing
+     * async.forEachOf(invalidConfigFileMap, parseFile)
+     * .then( () => {
+     *     console.log(configs);
+     * }).catch( err => {
+     *     console.error(err);
+     *     // JSON parse error exception
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let result = await async.forEachOf(validConfigFileMap, parseFile);
+     *         console.log(configs);
+     *         // configs is now a map of JSON data, e.g.
+     *         // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * //Error handing
+     * async () => {
+     *     try {
+     *         let result = await async.forEachOf(invalidConfigFileMap, parseFile);
+     *         console.log(configs);
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *         // JSON parse error exception
+     *     }
+     * }
+     *
+     */
+    function eachOf(coll, iteratee, callback) {
+        var eachOfImplementation = isArrayLike(coll) ? eachOfArrayLike : eachOfGeneric;
+        return eachOfImplementation(coll, wrapAsync(iteratee), callback);
+    }
+
+    var eachOf$1 = awaitify(eachOf, 3);
+
+    /**
+     * Produces a new collection of values by mapping each value in `coll` through
+     * the `iteratee` function. The `iteratee` is called with an item from `coll`
+     * and a callback for when it has finished processing. Each of these callbacks
+     * takes 2 arguments: an `error`, and the transformed item from `coll`. If
+     * `iteratee` passes an error to its callback, the main `callback` (for the
+     * `map` function) is immediately called with the error.
+     *
+     * Note, that since this function applies the `iteratee` to each item in
+     * parallel, there is no guarantee that the `iteratee` functions will complete
+     * in order. However, the results array will be in the same order as the
+     * original `coll`.
+     *
+     * If `map` is passed an Object, the results will be an Array.  The results
+     * will roughly be in the order of the original Objects' keys (but this can
+     * vary across JavaScript engines).
+     *
+     * @name map
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async function to apply to each item in
+     * `coll`.
+     * The iteratee should complete with the transformed item.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. Results is an Array of the
+     * transformed items from the `coll`. Invoked with (err, results).
+     * @returns {Promise} a promise, if no callback is passed
+     * @example
+     *
+     * // file1.txt is a file that is 1000 bytes in size
+     * // file2.txt is a file that is 2000 bytes in size
+     * // file3.txt is a file that is 3000 bytes in size
+     * // file4.txt does not exist
+     *
+     * const fileList = ['file1.txt','file2.txt','file3.txt'];
+     * const withMissingFileList = ['file1.txt','file2.txt','file4.txt'];
+     *
+     * // asynchronous function that returns the file size in bytes
+     * function getFileSizeInBytes(file, callback) {
+     *     fs.stat(file, function(err, stat) {
+     *         if (err) {
+     *             return callback(err);
+     *         }
+     *         callback(null, stat.size);
+     *     });
+     * }
+     *
+     * // Using callbacks
+     * async.map(fileList, getFileSizeInBytes, function(err, results) {
+     *     if (err) {
+     *         console.log(err);
+     *     } else {
+     *         console.log(results);
+     *         // results is now an array of the file size in bytes for each file, e.g.
+     *         // [ 1000, 2000, 3000]
+     *     }
+     * });
+     *
+     * // Error Handling
+     * async.map(withMissingFileList, getFileSizeInBytes, function(err, results) {
+     *     if (err) {
+     *         console.log(err);
+     *         // [ Error: ENOENT: no such file or directory ]
+     *     } else {
+     *         console.log(results);
+     *     }
+     * });
+     *
+     * // Using Promises
+     * async.map(fileList, getFileSizeInBytes)
+     * .then( results => {
+     *     console.log(results);
+     *     // results is now an array of the file size in bytes for each file, e.g.
+     *     // [ 1000, 2000, 3000]
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * // Error Handling
+     * async.map(withMissingFileList, getFileSizeInBytes)
+     * .then( results => {
+     *     console.log(results);
+     * }).catch( err => {
+     *     console.log(err);
+     *     // [ Error: ENOENT: no such file or directory ]
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let results = await async.map(fileList, getFileSizeInBytes);
+     *         console.log(results);
+     *         // results is now an array of the file size in bytes for each file, e.g.
+     *         // [ 1000, 2000, 3000]
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * // Error Handling
+     * async () => {
+     *     try {
+     *         let results = await async.map(withMissingFileList, getFileSizeInBytes);
+     *         console.log(results);
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *         // [ Error: ENOENT: no such file or directory ]
+     *     }
+     * }
+     *
+     */
+    function map (coll, iteratee, callback) {
+        return _asyncMap(eachOf$1, coll, iteratee, callback)
+    }
+    var map$1 = awaitify(map, 3);
+
+    /**
+     * Applies the provided arguments to each function in the array, calling
+     * `callback` after all functions have completed. If you only provide the first
+     * argument, `fns`, then it will return a function which lets you pass in the
+     * arguments as if it were a single function call. If more arguments are
+     * provided, `callback` is required while `args` is still optional. The results
+     * for each of the applied async functions are passed to the final callback
+     * as an array.
+     *
+     * @name applyEach
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s
+     * to all call with the same arguments
+     * @param {...*} [args] - any number of separate arguments to pass to the
+     * function.
+     * @param {Function} [callback] - the final argument should be the callback,
+     * called when all functions have completed processing.
+     * @returns {AsyncFunction} - Returns a function that takes no args other than
+     * an optional callback, that is the result of applying the `args` to each
+     * of the functions.
+     * @example
+     *
+     * const appliedFn = async.applyEach([enableSearch, updateSchema], 'bucket')
+     *
+     * appliedFn((err, results) => {
+     *     // results[0] is the results for `enableSearch`
+     *     // results[1] is the results for `updateSchema`
+     * });
+     *
+     * // partial application example:
+     * async.each(
+     *     buckets,
+     *     async (bucket) => async.applyEach([enableSearch, updateSchema], bucket)(),
+     *     callback
+     * );
+     */
+    var applyEach$1 = applyEach(map$1);
+
+    /**
+     * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time.
+     *
+     * @name eachOfSeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.eachOf]{@link module:Collections.eachOf}
+     * @alias forEachOfSeries
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async function to apply to each item in
+     * `coll`.
+     * Invoked with (item, key, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. Invoked with (err).
+     * @returns {Promise} a promise, if a callback is omitted
+     */
+    function eachOfSeries(coll, iteratee, callback) {
+        return eachOfLimit$2(coll, 1, iteratee, callback)
+    }
+    var eachOfSeries$1 = awaitify(eachOfSeries, 3);
+
+    /**
+     * The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time.
+     *
+     * @name mapSeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.map]{@link module:Collections.map}
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async function to apply to each item in
+     * `coll`.
+     * The iteratee should complete with the transformed item.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. Results is an array of the
+     * transformed items from the `coll`. Invoked with (err, results).
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function mapSeries (coll, iteratee, callback) {
+        return _asyncMap(eachOfSeries$1, coll, iteratee, callback)
+    }
+    var mapSeries$1 = awaitify(mapSeries, 3);
+
+    /**
+     * The same as [`applyEach`]{@link module:ControlFlow.applyEach} but runs only a single async operation at a time.
+     *
+     * @name applyEachSeries
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.applyEach]{@link module:ControlFlow.applyEach}
+     * @category Control Flow
+     * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s to all
+     * call with the same arguments
+     * @param {...*} [args] - any number of separate arguments to pass to the
+     * function.
+     * @param {Function} [callback] - the final argument should be the callback,
+     * called when all functions have completed processing.
+     * @returns {AsyncFunction} - A function, that when called, is the result of
+     * appling the `args` to the list of functions.  It takes no args, other than
+     * a callback.
+     */
+    var applyEachSeries = applyEach(mapSeries$1);
+
+    const PROMISE_SYMBOL = Symbol('promiseCallback');
+
+    function promiseCallback () {
+        let resolve, reject;
+        function callback (err, ...args) {
+            if (err) return reject(err)
+            resolve(args.length > 1 ? args : args[0]);
+        }
+
+        callback[PROMISE_SYMBOL] = new Promise((res, rej) => {
+            resolve = res,
+            reject = rej;
+        });
+
+        return callback
+    }
+
+    /**
+     * Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on
+     * their requirements. Each function can optionally depend on other functions
+     * being completed first, and each function is run as soon as its requirements
+     * are satisfied.
+     *
+     * If any of the {@link AsyncFunction}s pass an error to their callback, the `auto` sequence
+     * will stop. Further tasks will not execute (so any other functions depending
+     * on it will not run), and the main `callback` is immediately called with the
+     * error.
+     *
+     * {@link AsyncFunction}s also receive an object containing the results of functions which
+     * have completed so far as the first argument, if they have dependencies. If a
+     * task function has no dependencies, it will only be passed a callback.
+     *
+     * @name auto
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {Object} tasks - An object. Each of its properties is either a
+     * function or an array of requirements, with the {@link AsyncFunction} itself the last item
+     * in the array. The object's key of a property serves as the name of the task
+     * defined by that property, i.e. can be used when specifying requirements for
+     * other tasks. The function receives one or two arguments:
+     * * a `results` object, containing the results of the previously executed
+     *   functions, only passed if the task has any dependencies,
+     * * a `callback(err, result)` function, which must be called when finished,
+     *   passing an `error` (which can be `null`) and the result of the function's
+     *   execution.
+     * @param {number} [concurrency=Infinity] - An optional `integer` for
+     * determining the maximum number of tasks that can be run in parallel. By
+     * default, as many as possible.
+     * @param {Function} [callback] - An optional callback which is called when all
+     * the tasks have been completed. It receives the `err` argument if any `tasks`
+     * pass an error to their callback. Results are always returned; however, if an
+     * error occurs, no further `tasks` will be performed, and the results object
+     * will only contain partial results. Invoked with (err, results).
+     * @returns {Promise} a promise, if a callback is not passed
+     * @example
+     *
+     * //Using Callbacks
+     * async.auto({
+     *     get_data: function(callback) {
+     *         // async code to get some data
+     *         callback(null, 'data', 'converted to array');
+     *     },
+     *     make_folder: function(callback) {
+     *         // async code to create a directory to store a file in
+     *         // this is run at the same time as getting the data
+     *         callback(null, 'folder');
+     *     },
+     *     write_file: ['get_data', 'make_folder', function(results, callback) {
+     *         // once there is some data and the directory exists,
+     *         // write the data to a file in the directory
+     *         callback(null, 'filename');
+     *     }],
+     *     email_link: ['write_file', function(results, callback) {
+     *         // once the file is written let's email a link to it...
+     *         callback(null, {'file':results.write_file, 'email':'user@example.com'});
+     *     }]
+     * }, function(err, results) {
+     *     if (err) {
+     *         console.log('err = ', err);
+     *     }
+     *     console.log('results = ', results);
+     *     // results = {
+     *     //     get_data: ['data', 'converted to array']
+     *     //     make_folder; 'folder',
+     *     //     write_file: 'filename'
+     *     //     email_link: { file: 'filename', email: 'user@example.com' }
+     *     // }
+     * });
+     *
+     * //Using Promises
+     * async.auto({
+     *     get_data: function(callback) {
+     *         console.log('in get_data');
+     *         // async code to get some data
+     *         callback(null, 'data', 'converted to array');
+     *     },
+     *     make_folder: function(callback) {
+     *         console.log('in make_folder');
+     *         // async code to create a directory to store a file in
+     *         // this is run at the same time as getting the data
+     *         callback(null, 'folder');
+     *     },
+     *     write_file: ['get_data', 'make_folder', function(results, callback) {
+     *         // once there is some data and the directory exists,
+     *         // write the data to a file in the directory
+     *         callback(null, 'filename');
+     *     }],
+     *     email_link: ['write_file', function(results, callback) {
+     *         // once the file is written let's email a link to it...
+     *         callback(null, {'file':results.write_file, 'email':'user@example.com'});
+     *     }]
+     * }).then(results => {
+     *     console.log('results = ', results);
+     *     // results = {
+     *     //     get_data: ['data', 'converted to array']
+     *     //     make_folder; 'folder',
+     *     //     write_file: 'filename'
+     *     //     email_link: { file: 'filename', email: 'user@example.com' }
+     *     // }
+     * }).catch(err => {
+     *     console.log('err = ', err);
+     * });
+     *
+     * //Using async/await
+     * async () => {
+     *     try {
+     *         let results = await async.auto({
+     *             get_data: function(callback) {
+     *                 // async code to get some data
+     *                 callback(null, 'data', 'converted to array');
+     *             },
+     *             make_folder: function(callback) {
+     *                 // async code to create a directory to store a file in
+     *                 // this is run at the same time as getting the data
+     *                 callback(null, 'folder');
+     *             },
+     *             write_file: ['get_data', 'make_folder', function(results, callback) {
+     *                 // once there is some data and the directory exists,
+     *                 // write the data to a file in the directory
+     *                 callback(null, 'filename');
+     *             }],
+     *             email_link: ['write_file', function(results, callback) {
+     *                 // once the file is written let's email a link to it...
+     *                 callback(null, {'file':results.write_file, 'email':'user@example.com'});
+     *             }]
+     *         });
+     *         console.log('results = ', results);
+     *         // results = {
+     *         //     get_data: ['data', 'converted to array']
+     *         //     make_folder; 'folder',
+     *         //     write_file: 'filename'
+     *         //     email_link: { file: 'filename', email: 'user@example.com' }
+     *         // }
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function auto(tasks, concurrency, callback) {
+        if (typeof concurrency !== 'number') {
+            // concurrency is optional, shift the args.
+            callback = concurrency;
+            concurrency = null;
+        }
+        callback = once(callback || promiseCallback());
+        var numTasks = Object.keys(tasks).length;
+        if (!numTasks) {
+            return callback(null);
+        }
+        if (!concurrency) {
+            concurrency = numTasks;
+        }
+
+        var results = {};
+        var runningTasks = 0;
+        var canceled = false;
+        var hasError = false;
+
+        var listeners = Object.create(null);
+
+        var readyTasks = [];
+
+        // for cycle detection:
+        var readyToCheck = []; // tasks that have been identified as reachable
+        // without the possibility of returning to an ancestor task
+        var uncheckedDependencies = {};
+
+        Object.keys(tasks).forEach(key => {
+            var task = tasks[key];
+            if (!Array.isArray(task)) {
+                // no dependencies
+                enqueueTask(key, [task]);
+                readyToCheck.push(key);
+                return;
+            }
+
+            var dependencies = task.slice(0, task.length - 1);
+            var remainingDependencies = dependencies.length;
+            if (remainingDependencies === 0) {
+                enqueueTask(key, task);
+                readyToCheck.push(key);
+                return;
+            }
+            uncheckedDependencies[key] = remainingDependencies;
+
+            dependencies.forEach(dependencyName => {
+                if (!tasks[dependencyName]) {
+                    throw new Error('async.auto task `' + key +
+                        '` has a non-existent dependency `' +
+                        dependencyName + '` in ' +
+                        dependencies.join(', '));
+                }
+                addListener(dependencyName, () => {
+                    remainingDependencies--;
+                    if (remainingDependencies === 0) {
+                        enqueueTask(key, task);
+                    }
+                });
+            });
+        });
+
+        checkForDeadlocks();
+        processQueue();
+
+        function enqueueTask(key, task) {
+            readyTasks.push(() => runTask(key, task));
+        }
+
+        function processQueue() {
+            if (canceled) return
+            if (readyTasks.length === 0 && runningTasks === 0) {
+                return callback(null, results);
+            }
+            while(readyTasks.length && runningTasks < concurrency) {
+                var run = readyTasks.shift();
+                run();
+            }
+
+        }
+
+        function addListener(taskName, fn) {
+            var taskListeners = listeners[taskName];
+            if (!taskListeners) {
+                taskListeners = listeners[taskName] = [];
+            }
+
+            taskListeners.push(fn);
+        }
+
+        function taskComplete(taskName) {
+            var taskListeners = listeners[taskName] || [];
+            taskListeners.forEach(fn => fn());
+            processQueue();
+        }
+
+
+        function runTask(key, task) {
+            if (hasError) return;
+
+            var taskCallback = onlyOnce((err, ...result) => {
+                runningTasks--;
+                if (err === false) {
+                    canceled = true;
+                    return
+                }
+                if (result.length < 2) {
+                    [result] = result;
+                }
+                if (err) {
+                    var safeResults = {};
+                    Object.keys(results).forEach(rkey => {
+                        safeResults[rkey] = results[rkey];
+                    });
+                    safeResults[key] = result;
+                    hasError = true;
+                    listeners = Object.create(null);
+                    if (canceled) return
+                    callback(err, safeResults);
+                } else {
+                    results[key] = result;
+                    taskComplete(key);
+                }
+            });
+
+            runningTasks++;
+            var taskFn = wrapAsync(task[task.length - 1]);
+            if (task.length > 1) {
+                taskFn(results, taskCallback);
+            } else {
+                taskFn(taskCallback);
+            }
+        }
+
+        function checkForDeadlocks() {
+            // Kahn's algorithm
+            // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
+            // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html
+            var currentTask;
+            var counter = 0;
+            while (readyToCheck.length) {
+                currentTask = readyToCheck.pop();
+                counter++;
+                getDependents(currentTask).forEach(dependent => {
+                    if (--uncheckedDependencies[dependent] === 0) {
+                        readyToCheck.push(dependent);
+                    }
+                });
+            }
+
+            if (counter !== numTasks) {
+                throw new Error(
+                    'async.auto cannot execute tasks due to a recursive dependency'
+                );
+            }
+        }
+
+        function getDependents(taskName) {
+            var result = [];
+            Object.keys(tasks).forEach(key => {
+                const task = tasks[key];
+                if (Array.isArray(task) && task.indexOf(taskName) >= 0) {
+                    result.push(key);
+                }
+            });
+            return result;
+        }
+
+        return callback[PROMISE_SYMBOL]
+    }
+
+    var FN_ARGS = /^(?:async\s+)?(?:function)?\s*\w*\s*\(\s*([^)]+)\s*\)(?:\s*{)/;
+    var ARROW_FN_ARGS = /^(?:async\s+)?\(?\s*([^)=]+)\s*\)?(?:\s*=>)/;
+    var FN_ARG_SPLIT = /,/;
+    var FN_ARG = /(=.+)?(\s*)$/;
+
+    function stripComments(string) {
+        let stripped = '';
+        let index = 0;
+        let endBlockComment = string.indexOf('*/');
+        while (index < string.length) {
+            if (string[index] === '/' && string[index+1] === '/') {
+                // inline comment
+                let endIndex = string.indexOf('\n', index);
+                index = (endIndex === -1) ? string.length : endIndex;
+            } else if ((endBlockComment !== -1) && (string[index] === '/') && (string[index+1] === '*')) {
+                // block comment
+                let endIndex = string.indexOf('*/', index);
+                if (endIndex !== -1) {
+                    index = endIndex + 2;
+                    endBlockComment = string.indexOf('*/', index);
+                } else {
+                    stripped += string[index];
+                    index++;
+                }
+            } else {
+                stripped += string[index];
+                index++;
+            }
+        }
+        return stripped;
+    }
+
+    function parseParams(func) {
+        const src = stripComments(func.toString());
+        let match = src.match(FN_ARGS);
+        if (!match) {
+            match = src.match(ARROW_FN_ARGS);
+        }
+        if (!match) throw new Error('could not parse args in autoInject\nSource:\n' + src)
+        let [, args] = match;
+        return args
+            .replace(/\s/g, '')
+            .split(FN_ARG_SPLIT)
+            .map((arg) => arg.replace(FN_ARG, '').trim());
+    }
+
+    /**
+     * A dependency-injected version of the [async.auto]{@link module:ControlFlow.auto} function. Dependent
+     * tasks are specified as parameters to the function, after the usual callback
+     * parameter, with the parameter names matching the names of the tasks it
+     * depends on. This can provide even more readable task graphs which can be
+     * easier to maintain.
+     *
+     * If a final callback is specified, the task results are similarly injected,
+     * specified as named parameters after the initial error parameter.
+     *
+     * The autoInject function is purely syntactic sugar and its semantics are
+     * otherwise equivalent to [async.auto]{@link module:ControlFlow.auto}.
+     *
+     * @name autoInject
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.auto]{@link module:ControlFlow.auto}
+     * @category Control Flow
+     * @param {Object} tasks - An object, each of whose properties is an {@link AsyncFunction} of
+     * the form 'func([dependencies...], callback). The object's key of a property
+     * serves as the name of the task defined by that property, i.e. can be used
+     * when specifying requirements for other tasks.
+     * * The `callback` parameter is a `callback(err, result)` which must be called
+     *   when finished, passing an `error` (which can be `null`) and the result of
+     *   the function's execution. The remaining parameters name other tasks on
+     *   which the task is dependent, and the results from those tasks are the
+     *   arguments of those parameters.
+     * @param {Function} [callback] - An optional callback which is called when all
+     * the tasks have been completed. It receives the `err` argument if any `tasks`
+     * pass an error to their callback, and a `results` object with any completed
+     * task results, similar to `auto`.
+     * @returns {Promise} a promise, if no callback is passed
+     * @example
+     *
+     * //  The example from `auto` can be rewritten as follows:
+     * async.autoInject({
+     *     get_data: function(callback) {
+     *         // async code to get some data
+     *         callback(null, 'data', 'converted to array');
+     *     },
+     *     make_folder: function(callback) {
+     *         // async code to create a directory to store a file in
+     *         // this is run at the same time as getting the data
+     *         callback(null, 'folder');
+     *     },
+     *     write_file: function(get_data, make_folder, callback) {
+     *         // once there is some data and the directory exists,
+     *         // write the data to a file in the directory
+     *         callback(null, 'filename');
+     *     },
+     *     email_link: function(write_file, callback) {
+     *         // once the file is written let's email a link to it...
+     *         // write_file contains the filename returned by write_file.
+     *         callback(null, {'file':write_file, 'email':'user@example.com'});
+     *     }
+     * }, function(err, results) {
+     *     console.log('err = ', err);
+     *     console.log('email_link = ', results.email_link);
+     * });
+     *
+     * // If you are using a JS minifier that mangles parameter names, `autoInject`
+     * // will not work with plain functions, since the parameter names will be
+     * // collapsed to a single letter identifier.  To work around this, you can
+     * // explicitly specify the names of the parameters your task function needs
+     * // in an array, similar to Angular.js dependency injection.
+     *
+     * // This still has an advantage over plain `auto`, since the results a task
+     * // depends on are still spread into arguments.
+     * async.autoInject({
+     *     //...
+     *     write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) {
+     *         callback(null, 'filename');
+     *     }],
+     *     email_link: ['write_file', function(write_file, callback) {
+     *         callback(null, {'file':write_file, 'email':'user@example.com'});
+     *     }]
+     *     //...
+     * }, function(err, results) {
+     *     console.log('err = ', err);
+     *     console.log('email_link = ', results.email_link);
+     * });
+     */
+    function autoInject(tasks, callback) {
+        var newTasks = {};
+
+        Object.keys(tasks).forEach(key => {
+            var taskFn = tasks[key];
+            var params;
+            var fnIsAsync = isAsync(taskFn);
+            var hasNoDeps =
+                (!fnIsAsync && taskFn.length === 1) ||
+                (fnIsAsync && taskFn.length === 0);
+
+            if (Array.isArray(taskFn)) {
+                params = [...taskFn];
+                taskFn = params.pop();
+
+                newTasks[key] = params.concat(params.length > 0 ? newTask : taskFn);
+            } else if (hasNoDeps) {
+                // no dependencies, use the function as-is
+                newTasks[key] = taskFn;
+            } else {
+                params = parseParams(taskFn);
+                if ((taskFn.length === 0 && !fnIsAsync) && params.length === 0) {
+                    throw new Error("autoInject task functions require explicit parameters.");
+                }
+
+                // remove callback param
+                if (!fnIsAsync) params.pop();
+
+                newTasks[key] = params.concat(newTask);
+            }
+
+            function newTask(results, taskCb) {
+                var newArgs = params.map(name => results[name]);
+                newArgs.push(taskCb);
+                wrapAsync(taskFn)(...newArgs);
+            }
+        });
+
+        return auto(newTasks, callback);
+    }
+
+    // Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation
+    // used for queues. This implementation assumes that the node provided by the user can be modified
+    // to adjust the next and last properties. We implement only the minimal functionality
+    // for queue support.
+    class DLL {
+        constructor() {
+            this.head = this.tail = null;
+            this.length = 0;
+        }
+
+        removeLink(node) {
+            if (node.prev) node.prev.next = node.next;
+            else this.head = node.next;
+            if (node.next) node.next.prev = node.prev;
+            else this.tail = node.prev;
+
+            node.prev = node.next = null;
+            this.length -= 1;
+            return node;
+        }
+
+        empty () {
+            while(this.head) this.shift();
+            return this;
+        }
+
+        insertAfter(node, newNode) {
+            newNode.prev = node;
+            newNode.next = node.next;
+            if (node.next) node.next.prev = newNode;
+            else this.tail = newNode;
+            node.next = newNode;
+            this.length += 1;
+        }
+
+        insertBefore(node, newNode) {
+            newNode.prev = node.prev;
+            newNode.next = node;
+            if (node.prev) node.prev.next = newNode;
+            else this.head = newNode;
+            node.prev = newNode;
+            this.length += 1;
+        }
+
+        unshift(node) {
+            if (this.head) this.insertBefore(this.head, node);
+            else setInitial(this, node);
+        }
+
+        push(node) {
+            if (this.tail) this.insertAfter(this.tail, node);
+            else setInitial(this, node);
+        }
+
+        shift() {
+            return this.head && this.removeLink(this.head);
+        }
+
+        pop() {
+            return this.tail && this.removeLink(this.tail);
+        }
+
+        toArray() {
+            return [...this]
+        }
+
+        *[Symbol.iterator] () {
+            var cur = this.head;
+            while (cur) {
+                yield cur.data;
+                cur = cur.next;
+            }
+        }
+
+        remove (testFn) {
+            var curr = this.head;
+            while(curr) {
+                var {next} = curr;
+                if (testFn(curr)) {
+                    this.removeLink(curr);
+                }
+                curr = next;
+            }
+            return this;
+        }
+    }
+
+    function setInitial(dll, node) {
+        dll.length = 1;
+        dll.head = dll.tail = node;
+    }
+
+    function queue(worker, concurrency, payload) {
+        if (concurrency == null) {
+            concurrency = 1;
+        }
+        else if(concurrency === 0) {
+            throw new RangeError('Concurrency must not be zero');
+        }
+
+        var _worker = wrapAsync(worker);
+        var numRunning = 0;
+        var workersList = [];
+        const events = {
+            error: [],
+            drain: [],
+            saturated: [],
+            unsaturated: [],
+            empty: []
+        };
+
+        function on (event, handler) {
+            events[event].push(handler);
+        }
+
+        function once (event, handler) {
+            const handleAndRemove = (...args) => {
+                off(event, handleAndRemove);
+                handler(...args);
+            };
+            events[event].push(handleAndRemove);
+        }
+
+        function off (event, handler) {
+            if (!event) return Object.keys(events).forEach(ev => events[ev] = [])
+            if (!handler) return events[event] = []
+            events[event] = events[event].filter(ev => ev !== handler);
+        }
+
+        function trigger (event, ...args) {
+            events[event].forEach(handler => handler(...args));
+        }
+
+        var processingScheduled = false;
+        function _insert(data, insertAtFront, rejectOnError, callback) {
+            if (callback != null && typeof callback !== 'function') {
+                throw new Error('task callback must be a function');
+            }
+            q.started = true;
+
+            var res, rej;
+            function promiseCallback (err, ...args) {
+                // we don't care about the error, let the global error handler
+                // deal with it
+                if (err) return rejectOnError ? rej(err) : res()
+                if (args.length <= 1) return res(args[0])
+                res(args);
+            }
+
+            var item = q._createTaskItem(
+                data,
+                rejectOnError ? promiseCallback :
+                    (callback || promiseCallback)
+            );
+
+            if (insertAtFront) {
+                q._tasks.unshift(item);
+            } else {
+                q._tasks.push(item);
+            }
+
+            if (!processingScheduled) {
+                processingScheduled = true;
+                setImmediate$1(() => {
+                    processingScheduled = false;
+                    q.process();
+                });
+            }
+
+            if (rejectOnError || !callback) {
+                return new Promise((resolve, reject) => {
+                    res = resolve;
+                    rej = reject;
+                })
+            }
+        }
+
+        function _createCB(tasks) {
+            return function (err, ...args) {
+                numRunning -= 1;
+
+                for (var i = 0, l = tasks.length; i < l; i++) {
+                    var task = tasks[i];
+
+                    var index = workersList.indexOf(task);
+                    if (index === 0) {
+                        workersList.shift();
+                    } else if (index > 0) {
+                        workersList.splice(index, 1);
+                    }
+
+                    task.callback(err, ...args);
+
+                    if (err != null) {
+                        trigger('error', err, task.data);
+                    }
+                }
+
+                if (numRunning <= (q.concurrency - q.buffer) ) {
+                    trigger('unsaturated');
+                }
+
+                if (q.idle()) {
+                    trigger('drain');
+                }
+                q.process();
+            };
+        }
+
+        function _maybeDrain(data) {
+            if (data.length === 0 && q.idle()) {
+                // call drain immediately if there are no tasks
+                setImmediate$1(() => trigger('drain'));
+                return true
+            }
+            return false
+        }
+
+        const eventMethod = (name) => (handler) => {
+            if (!handler) {
+                return new Promise((resolve, reject) => {
+                    once(name, (err, data) => {
+                        if (err) return reject(err)
+                        resolve(data);
+                    });
+                })
+            }
+            off(name);
+            on(name, handler);
+
+        };
+
+        var isProcessing = false;
+        var q = {
+            _tasks: new DLL(),
+            _createTaskItem (data, callback) {
+                return {
+                    data,
+                    callback
+                };
+            },
+            *[Symbol.iterator] () {
+                yield* q._tasks[Symbol.iterator]();
+            },
+            concurrency,
+            payload,
+            buffer: concurrency / 4,
+            started: false,
+            paused: false,
+            push (data, callback) {
+                if (Array.isArray(data)) {
+                    if (_maybeDrain(data)) return
+                    return data.map(datum => _insert(datum, false, false, callback))
+                }
+                return _insert(data, false, false, callback);
+            },
+            pushAsync (data, callback) {
+                if (Array.isArray(data)) {
+                    if (_maybeDrain(data)) return
+                    return data.map(datum => _insert(datum, false, true, callback))
+                }
+                return _insert(data, false, true, callback);
+            },
+            kill () {
+                off();
+                q._tasks.empty();
+            },
+            unshift (data, callback) {
+                if (Array.isArray(data)) {
+                    if (_maybeDrain(data)) return
+                    return data.map(datum => _insert(datum, true, false, callback))
+                }
+                return _insert(data, true, false, callback);
+            },
+            unshiftAsync (data, callback) {
+                if (Array.isArray(data)) {
+                    if (_maybeDrain(data)) return
+                    return data.map(datum => _insert(datum, true, true, callback))
+                }
+                return _insert(data, true, true, callback);
+            },
+            remove (testFn) {
+                q._tasks.remove(testFn);
+            },
+            process () {
+                // Avoid trying to start too many processing operations. This can occur
+                // when callbacks resolve synchronously (#1267).
+                if (isProcessing) {
+                    return;
+                }
+                isProcessing = true;
+                while(!q.paused && numRunning < q.concurrency && q._tasks.length){
+                    var tasks = [], data = [];
+                    var l = q._tasks.length;
+                    if (q.payload) l = Math.min(l, q.payload);
+                    for (var i = 0; i < l; i++) {
+                        var node = q._tasks.shift();
+                        tasks.push(node);
+                        workersList.push(node);
+                        data.push(node.data);
+                    }
+
+                    numRunning += 1;
+
+                    if (q._tasks.length === 0) {
+                        trigger('empty');
+                    }
+
+                    if (numRunning === q.concurrency) {
+                        trigger('saturated');
+                    }
+
+                    var cb = onlyOnce(_createCB(tasks));
+                    _worker(data, cb);
+                }
+                isProcessing = false;
+            },
+            length () {
+                return q._tasks.length;
+            },
+            running () {
+                return numRunning;
+            },
+            workersList () {
+                return workersList;
+            },
+            idle() {
+                return q._tasks.length + numRunning === 0;
+            },
+            pause () {
+                q.paused = true;
+            },
+            resume () {
+                if (q.paused === false) { return; }
+                q.paused = false;
+                setImmediate$1(q.process);
+            }
+        };
+        // define these as fixed properties, so people get useful errors when updating
+        Object.defineProperties(q, {
+            saturated: {
+                writable: false,
+                value: eventMethod('saturated')
+            },
+            unsaturated: {
+                writable: false,
+                value: eventMethod('unsaturated')
+            },
+            empty: {
+                writable: false,
+                value: eventMethod('empty')
+            },
+            drain: {
+                writable: false,
+                value: eventMethod('drain')
+            },
+            error: {
+                writable: false,
+                value: eventMethod('error')
+            },
+        });
+        return q;
+    }
+
+    /**
+     * Creates a `cargo` object with the specified payload. Tasks added to the
+     * cargo will be processed altogether (up to the `payload` limit). If the
+     * `worker` is in progress, the task is queued until it becomes available. Once
+     * the `worker` has completed some tasks, each callback of those tasks is
+     * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966)
+     * for how `cargo` and `queue` work.
+     *
+     * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers
+     * at a time, cargo passes an array of tasks to a single worker, repeating
+     * when the worker is finished.
+     *
+     * @name cargo
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.queue]{@link module:ControlFlow.queue}
+     * @category Control Flow
+     * @param {AsyncFunction} worker - An asynchronous function for processing an array
+     * of queued tasks. Invoked with `(tasks, callback)`.
+     * @param {number} [payload=Infinity] - An optional `integer` for determining
+     * how many tasks should be processed per round; if omitted, the default is
+     * unlimited.
+     * @returns {module:ControlFlow.QueueObject} A cargo object to manage the tasks. Callbacks can
+     * attached as certain properties to listen for specific events during the
+     * lifecycle of the cargo and inner queue.
+     * @example
+     *
+     * // create a cargo object with payload 2
+     * var cargo = async.cargo(function(tasks, callback) {
+     *     for (var i=0; i<tasks.length; i++) {
+     *         console.log('hello ' + tasks[i].name);
+     *     }
+     *     callback();
+     * }, 2);
+     *
+     * // add some items
+     * cargo.push({name: 'foo'}, function(err) {
+     *     console.log('finished processing foo');
+     * });
+     * cargo.push({name: 'bar'}, function(err) {
+     *     console.log('finished processing bar');
+     * });
+     * await cargo.push({name: 'baz'});
+     * console.log('finished processing baz');
+     */
+    function cargo(worker, payload) {
+        return queue(worker, 1, payload);
+    }
+
+    /**
+     * Creates a `cargoQueue` object with the specified payload. Tasks added to the
+     * cargoQueue will be processed together (up to the `payload` limit) in `concurrency` parallel workers.
+     * If the all `workers` are in progress, the task is queued until one becomes available. Once
+     * a `worker` has completed some tasks, each callback of those tasks is
+     * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966)
+     * for how `cargo` and `queue` work.
+     *
+     * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers
+     * at a time, and [`cargo`]{@link module:ControlFlow.cargo} passes an array of tasks to a single worker,
+     * the cargoQueue passes an array of tasks to multiple parallel workers.
+     *
+     * @name cargoQueue
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.queue]{@link module:ControlFlow.queue}
+     * @see [async.cargo]{@link module:ControlFLow.cargo}
+     * @category Control Flow
+     * @param {AsyncFunction} worker - An asynchronous function for processing an array
+     * of queued tasks. Invoked with `(tasks, callback)`.
+     * @param {number} [concurrency=1] - An `integer` for determining how many
+     * `worker` functions should be run in parallel.  If omitted, the concurrency
+     * defaults to `1`.  If the concurrency is `0`, an error is thrown.
+     * @param {number} [payload=Infinity] - An optional `integer` for determining
+     * how many tasks should be processed per round; if omitted, the default is
+     * unlimited.
+     * @returns {module:ControlFlow.QueueObject} A cargoQueue object to manage the tasks. Callbacks can
+     * attached as certain properties to listen for specific events during the
+     * lifecycle of the cargoQueue and inner queue.
+     * @example
+     *
+     * // create a cargoQueue object with payload 2 and concurrency 2
+     * var cargoQueue = async.cargoQueue(function(tasks, callback) {
+     *     for (var i=0; i<tasks.length; i++) {
+     *         console.log('hello ' + tasks[i].name);
+     *     }
+     *     callback();
+     * }, 2, 2);
+     *
+     * // add some items
+     * cargoQueue.push({name: 'foo'}, function(err) {
+     *     console.log('finished processing foo');
+     * });
+     * cargoQueue.push({name: 'bar'}, function(err) {
+     *     console.log('finished processing bar');
+     * });
+     * cargoQueue.push({name: 'baz'}, function(err) {
+     *     console.log('finished processing baz');
+     * });
+     * cargoQueue.push({name: 'boo'}, function(err) {
+     *     console.log('finished processing boo');
+     * });
+     */
+    function cargo$1(worker, concurrency, payload) {
+        return queue(worker, concurrency, payload);
+    }
+
+    /**
+     * Reduces `coll` into a single value using an async `iteratee` to return each
+     * successive step. `memo` is the initial state of the reduction. This function
+     * only operates in series.
+     *
+     * For performance reasons, it may make sense to split a call to this function
+     * into a parallel map, and then use the normal `Array.prototype.reduce` on the
+     * results. This function is for situations where each step in the reduction
+     * needs to be async; if you can get the data before reducing it, then it's
+     * probably a good idea to do so.
+     *
+     * @name reduce
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @alias inject
+     * @alias foldl
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {*} memo - The initial state of the reduction.
+     * @param {AsyncFunction} iteratee - A function applied to each item in the
+     * array to produce the next step in the reduction.
+     * The `iteratee` should complete with the next state of the reduction.
+     * If the iteratee completes with an error, the reduction is stopped and the
+     * main `callback` is immediately called with the error.
+     * Invoked with (memo, item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Result is the reduced value. Invoked with
+     * (err, result).
+     * @returns {Promise} a promise, if no callback is passed
+     * @example
+     *
+     * // file1.txt is a file that is 1000 bytes in size
+     * // file2.txt is a file that is 2000 bytes in size
+     * // file3.txt is a file that is 3000 bytes in size
+     * // file4.txt does not exist
+     *
+     * const fileList = ['file1.txt','file2.txt','file3.txt'];
+     * const withMissingFileList = ['file1.txt','file2.txt','file3.txt', 'file4.txt'];
+     *
+     * // asynchronous function that computes the file size in bytes
+     * // file size is added to the memoized value, then returned
+     * function getFileSizeInBytes(memo, file, callback) {
+     *     fs.stat(file, function(err, stat) {
+     *         if (err) {
+     *             return callback(err);
+     *         }
+     *         callback(null, memo + stat.size);
+     *     });
+     * }
+     *
+     * // Using callbacks
+     * async.reduce(fileList, 0, getFileSizeInBytes, function(err, result) {
+     *     if (err) {
+     *         console.log(err);
+     *     } else {
+     *         console.log(result);
+     *         // 6000
+     *         // which is the sum of the file sizes of the three files
+     *     }
+     * });
+     *
+     * // Error Handling
+     * async.reduce(withMissingFileList, 0, getFileSizeInBytes, function(err, result) {
+     *     if (err) {
+     *         console.log(err);
+     *         // [ Error: ENOENT: no such file or directory ]
+     *     } else {
+     *         console.log(result);
+     *     }
+     * });
+     *
+     * // Using Promises
+     * async.reduce(fileList, 0, getFileSizeInBytes)
+     * .then( result => {
+     *     console.log(result);
+     *     // 6000
+     *     // which is the sum of the file sizes of the three files
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * // Error Handling
+     * async.reduce(withMissingFileList, 0, getFileSizeInBytes)
+     * .then( result => {
+     *     console.log(result);
+     * }).catch( err => {
+     *     console.log(err);
+     *     // [ Error: ENOENT: no such file or directory ]
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let result = await async.reduce(fileList, 0, getFileSizeInBytes);
+     *         console.log(result);
+     *         // 6000
+     *         // which is the sum of the file sizes of the three files
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * // Error Handling
+     * async () => {
+     *     try {
+     *         let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes);
+     *         console.log(result);
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *         // [ Error: ENOENT: no such file or directory ]
+     *     }
+     * }
+     *
+     */
+    function reduce(coll, memo, iteratee, callback) {
+        callback = once(callback);
+        var _iteratee = wrapAsync(iteratee);
+        return eachOfSeries$1(coll, (x, i, iterCb) => {
+            _iteratee(memo, x, (err, v) => {
+                memo = v;
+                iterCb(err);
+            });
+        }, err => callback(err, memo));
+    }
+    var reduce$1 = awaitify(reduce, 4);
+
+    /**
+     * Version of the compose function that is more natural to read. Each function
+     * consumes the return value of the previous function. It is the equivalent of
+     * [compose]{@link module:ControlFlow.compose} with the arguments reversed.
+     *
+     * Each function is executed with the `this` binding of the composed function.
+     *
+     * @name seq
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.compose]{@link module:ControlFlow.compose}
+     * @category Control Flow
+     * @param {...AsyncFunction} functions - the asynchronous functions to compose
+     * @returns {Function} a function that composes the `functions` in order
+     * @example
+     *
+     * // Requires lodash (or underscore), express3 and dresende's orm2.
+     * // Part of an app, that fetches cats of the logged user.
+     * // This example uses `seq` function to avoid overnesting and error
+     * // handling clutter.
+     * app.get('/cats', function(request, response) {
+     *     var User = request.models.User;
+     *     async.seq(
+     *         User.get.bind(User),  // 'User.get' has signature (id, callback(err, data))
+     *         function(user, fn) {
+     *             user.getCats(fn);      // 'getCats' has signature (callback(err, data))
+     *         }
+     *     )(req.session.user_id, function (err, cats) {
+     *         if (err) {
+     *             console.error(err);
+     *             response.json({ status: 'error', message: err.message });
+     *         } else {
+     *             response.json({ status: 'ok', message: 'Cats found', data: cats });
+     *         }
+     *     });
+     * });
+     */
+    function seq(...functions) {
+        var _functions = functions.map(wrapAsync);
+        return function (...args) {
+            var that = this;
+
+            var cb = args[args.length - 1];
+            if (typeof cb == 'function') {
+                args.pop();
+            } else {
+                cb = promiseCallback();
+            }
+
+            reduce$1(_functions, args, (newargs, fn, iterCb) => {
+                fn.apply(that, newargs.concat((err, ...nextargs) => {
+                    iterCb(err, nextargs);
+                }));
+            },
+            (err, results) => cb(err, ...results));
+
+            return cb[PROMISE_SYMBOL]
+        };
+    }
+
+    /**
+     * Creates a function which is a composition of the passed asynchronous
+     * functions. Each function consumes the return value of the function that
+     * follows. Composing functions `f()`, `g()`, and `h()` would produce the result
+     * of `f(g(h()))`, only this version uses callbacks to obtain the return values.
+     *
+     * If the last argument to the composed function is not a function, a promise
+     * is returned when you call it.
+     *
+     * Each function is executed with the `this` binding of the composed function.
+     *
+     * @name compose
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {...AsyncFunction} functions - the asynchronous functions to compose
+     * @returns {Function} an asynchronous function that is the composed
+     * asynchronous `functions`
+     * @example
+     *
+     * function add1(n, callback) {
+     *     setTimeout(function () {
+     *         callback(null, n + 1);
+     *     }, 10);
+     * }
+     *
+     * function mul3(n, callback) {
+     *     setTimeout(function () {
+     *         callback(null, n * 3);
+     *     }, 10);
+     * }
+     *
+     * var add1mul3 = async.compose(mul3, add1);
+     * add1mul3(4, function (err, result) {
+     *     // result now equals 15
+     * });
+     */
+    function compose(...args) {
+        return seq(...args.reverse());
+    }
+
+    /**
+     * The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time.
+     *
+     * @name mapLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.map]{@link module:Collections.map}
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - An async function to apply to each item in
+     * `coll`.
+     * The iteratee should complete with the transformed item.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. Results is an array of the
+     * transformed items from the `coll`. Invoked with (err, results).
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function mapLimit (coll, limit, iteratee, callback) {
+        return _asyncMap(eachOfLimit(limit), coll, iteratee, callback)
+    }
+    var mapLimit$1 = awaitify(mapLimit, 4);
+
+    /**
+     * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time.
+     *
+     * @name concatLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.concat]{@link module:Collections.concat}
+     * @category Collection
+     * @alias flatMapLimit
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
+     * which should use an array as its result. Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished, or an error occurs. Results is an array
+     * containing the concatenated results of the `iteratee` function. Invoked with
+     * (err, results).
+     * @returns A Promise, if no callback is passed
+     */
+    function concatLimit(coll, limit, iteratee, callback) {
+        var _iteratee = wrapAsync(iteratee);
+        return mapLimit$1(coll, limit, (val, iterCb) => {
+            _iteratee(val, (err, ...args) => {
+                if (err) return iterCb(err);
+                return iterCb(err, args);
+            });
+        }, (err, mapResults) => {
+            var result = [];
+            for (var i = 0; i < mapResults.length; i++) {
+                if (mapResults[i]) {
+                    result = result.concat(...mapResults[i]);
+                }
+            }
+
+            return callback(err, result);
+        });
+    }
+    var concatLimit$1 = awaitify(concatLimit, 4);
+
+    /**
+     * Applies `iteratee` to each item in `coll`, concatenating the results. Returns
+     * the concatenated list. The `iteratee`s are called in parallel, and the
+     * results are concatenated as they return. The results array will be returned in
+     * the original order of `coll` passed to the `iteratee` function.
+     *
+     * @name concat
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @category Collection
+     * @alias flatMap
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
+     * which should use an array as its result. Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished, or an error occurs. Results is an array
+     * containing the concatenated results of the `iteratee` function. Invoked with
+     * (err, results).
+     * @returns A Promise, if no callback is passed
+     * @example
+     *
+     * // dir1 is a directory that contains file1.txt, file2.txt
+     * // dir2 is a directory that contains file3.txt, file4.txt
+     * // dir3 is a directory that contains file5.txt
+     * // dir4 does not exist
+     *
+     * let directoryList = ['dir1','dir2','dir3'];
+     * let withMissingDirectoryList = ['dir1','dir2','dir3', 'dir4'];
+     *
+     * // Using callbacks
+     * async.concat(directoryList, fs.readdir, function(err, results) {
+     *    if (err) {
+     *        console.log(err);
+     *    } else {
+     *        console.log(results);
+     *        // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+     *    }
+     * });
+     *
+     * // Error Handling
+     * async.concat(withMissingDirectoryList, fs.readdir, function(err, results) {
+     *    if (err) {
+     *        console.log(err);
+     *        // [ Error: ENOENT: no such file or directory ]
+     *        // since dir4 does not exist
+     *    } else {
+     *        console.log(results);
+     *    }
+     * });
+     *
+     * // Using Promises
+     * async.concat(directoryList, fs.readdir)
+     * .then(results => {
+     *     console.log(results);
+     *     // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+     * }).catch(err => {
+     *      console.log(err);
+     * });
+     *
+     * // Error Handling
+     * async.concat(withMissingDirectoryList, fs.readdir)
+     * .then(results => {
+     *     console.log(results);
+     * }).catch(err => {
+     *     console.log(err);
+     *     // [ Error: ENOENT: no such file or directory ]
+     *     // since dir4 does not exist
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let results = await async.concat(directoryList, fs.readdir);
+     *         console.log(results);
+     *         // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+     *     } catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * // Error Handling
+     * async () => {
+     *     try {
+     *         let results = await async.concat(withMissingDirectoryList, fs.readdir);
+     *         console.log(results);
+     *     } catch (err) {
+     *         console.log(err);
+     *         // [ Error: ENOENT: no such file or directory ]
+     *         // since dir4 does not exist
+     *     }
+     * }
+     *
+     */
+    function concat(coll, iteratee, callback) {
+        return concatLimit$1(coll, Infinity, iteratee, callback)
+    }
+    var concat$1 = awaitify(concat, 3);
+
+    /**
+     * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time.
+     *
+     * @name concatSeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.concat]{@link module:Collections.concat}
+     * @category Collection
+     * @alias flatMapSeries
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`.
+     * The iteratee should complete with an array an array of results.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished, or an error occurs. Results is an array
+     * containing the concatenated results of the `iteratee` function. Invoked with
+     * (err, results).
+     * @returns A Promise, if no callback is passed
+     */
+    function concatSeries(coll, iteratee, callback) {
+        return concatLimit$1(coll, 1, iteratee, callback)
+    }
+    var concatSeries$1 = awaitify(concatSeries, 3);
+
+    /**
+     * Returns a function that when called, calls-back with the values provided.
+     * Useful as the first function in a [`waterfall`]{@link module:ControlFlow.waterfall}, or for plugging values in to
+     * [`auto`]{@link module:ControlFlow.auto}.
+     *
+     * @name constant
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @category Util
+     * @param {...*} arguments... - Any number of arguments to automatically invoke
+     * callback with.
+     * @returns {AsyncFunction} Returns a function that when invoked, automatically
+     * invokes the callback with the previous given arguments.
+     * @example
+     *
+     * async.waterfall([
+     *     async.constant(42),
+     *     function (value, next) {
+     *         // value === 42
+     *     },
+     *     //...
+     * ], callback);
+     *
+     * async.waterfall([
+     *     async.constant(filename, "utf8"),
+     *     fs.readFile,
+     *     function (fileData, next) {
+     *         //...
+     *     }
+     *     //...
+     * ], callback);
+     *
+     * async.auto({
+     *     hostname: async.constant("https://server.net/"),
+     *     port: findFreePort,
+     *     launchServer: ["hostname", "port", function (options, cb) {
+     *         startServer(options, cb);
+     *     }],
+     *     //...
+     * }, callback);
+     */
+    function constant(...args) {
+        return function (...ignoredArgs/*, callback*/) {
+            var callback = ignoredArgs.pop();
+            return callback(null, ...args);
+        };
+    }
+
+    function _createTester(check, getResult) {
+        return (eachfn, arr, _iteratee, cb) => {
+            var testPassed = false;
+            var testResult;
+            const iteratee = wrapAsync(_iteratee);
+            eachfn(arr, (value, _, callback) => {
+                iteratee(value, (err, result) => {
+                    if (err || err === false) return callback(err);
+
+                    if (check(result) && !testResult) {
+                        testPassed = true;
+                        testResult = getResult(true, value);
+                        return callback(null, breakLoop);
+                    }
+                    callback();
+                });
+            }, err => {
+                if (err) return cb(err);
+                cb(null, testPassed ? testResult : getResult(false));
+            });
+        };
+    }
+
+    /**
+     * Returns the first value in `coll` that passes an async truth test. The
+     * `iteratee` is applied in parallel, meaning the first iteratee to return
+     * `true` will fire the detect `callback` with that result. That means the
+     * result might not be the first item in the original `coll` (in terms of order)
+     * that passes the test.
+
+     * If order within the original `coll` is important, then look at
+     * [`detectSeries`]{@link module:Collections.detectSeries}.
+     *
+     * @name detect
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @alias find
+     * @category Collections
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+     * The iteratee must complete with a boolean value as its result.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called as soon as any
+     * iteratee returns `true`, or after all the `iteratee` functions have finished.
+     * Result will be the first item in the array that passes the truth test
+     * (iteratee) or the value `undefined` if none passed. Invoked with
+     * (err, result).
+     * @returns {Promise} a promise, if a callback is omitted
+     * @example
+     *
+     * // dir1 is a directory that contains file1.txt, file2.txt
+     * // dir2 is a directory that contains file3.txt, file4.txt
+     * // dir3 is a directory that contains file5.txt
+     *
+     * // asynchronous function that checks if a file exists
+     * function fileExists(file, callback) {
+     *    fs.access(file, fs.constants.F_OK, (err) => {
+     *        callback(null, !err);
+     *    });
+     * }
+     *
+     * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists,
+     *    function(err, result) {
+     *        console.log(result);
+     *        // dir1/file1.txt
+     *        // result now equals the first file in the list that exists
+     *    }
+     *);
+     *
+     * // Using Promises
+     * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists)
+     * .then(result => {
+     *     console.log(result);
+     *     // dir1/file1.txt
+     *     // result now equals the first file in the list that exists
+     * }).catch(err => {
+     *     console.log(err);
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let result = await async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists);
+     *         console.log(result);
+     *         // dir1/file1.txt
+     *         // result now equals the file in the list that exists
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function detect(coll, iteratee, callback) {
+        return _createTester(bool => bool, (res, item) => item)(eachOf$1, coll, iteratee, callback)
+    }
+    var detect$1 = awaitify(detect, 3);
+
+    /**
+     * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a
+     * time.
+     *
+     * @name detectLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.detect]{@link module:Collections.detect}
+     * @alias findLimit
+     * @category Collections
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+     * The iteratee must complete with a boolean value as its result.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called as soon as any
+     * iteratee returns `true`, or after all the `iteratee` functions have finished.
+     * Result will be the first item in the array that passes the truth test
+     * (iteratee) or the value `undefined` if none passed. Invoked with
+     * (err, result).
+     * @returns {Promise} a promise, if a callback is omitted
+     */
+    function detectLimit(coll, limit, iteratee, callback) {
+        return _createTester(bool => bool, (res, item) => item)(eachOfLimit(limit), coll, iteratee, callback)
+    }
+    var detectLimit$1 = awaitify(detectLimit, 4);
+
+    /**
+     * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time.
+     *
+     * @name detectSeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.detect]{@link module:Collections.detect}
+     * @alias findSeries
+     * @category Collections
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+     * The iteratee must complete with a boolean value as its result.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called as soon as any
+     * iteratee returns `true`, or after all the `iteratee` functions have finished.
+     * Result will be the first item in the array that passes the truth test
+     * (iteratee) or the value `undefined` if none passed. Invoked with
+     * (err, result).
+     * @returns {Promise} a promise, if a callback is omitted
+     */
+    function detectSeries(coll, iteratee, callback) {
+        return _createTester(bool => bool, (res, item) => item)(eachOfLimit(1), coll, iteratee, callback)
+    }
+
+    var detectSeries$1 = awaitify(detectSeries, 3);
+
+    function consoleFunc(name) {
+        return (fn, ...args) => wrapAsync(fn)(...args, (err, ...resultArgs) => {
+            /* istanbul ignore else */
+            if (typeof console === 'object') {
+                /* istanbul ignore else */
+                if (err) {
+                    /* istanbul ignore else */
+                    if (console.error) {
+                        console.error(err);
+                    }
+                } else if (console[name]) { /* istanbul ignore else */
+                    resultArgs.forEach(x => console[name](x));
+                }
+            }
+        })
+    }
+
+    /**
+     * Logs the result of an [`async` function]{@link AsyncFunction} to the
+     * `console` using `console.dir` to display the properties of the resulting object.
+     * Only works in Node.js or in browsers that support `console.dir` and
+     * `console.error` (such as FF and Chrome).
+     * If multiple arguments are returned from the async function,
+     * `console.dir` is called on each argument in order.
+     *
+     * @name dir
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @category Util
+     * @param {AsyncFunction} function - The function you want to eventually apply
+     * all arguments to.
+     * @param {...*} arguments... - Any number of arguments to apply to the function.
+     * @example
+     *
+     * // in a module
+     * var hello = function(name, callback) {
+     *     setTimeout(function() {
+     *         callback(null, {hello: name});
+     *     }, 1000);
+     * };
+     *
+     * // in the node repl
+     * node> async.dir(hello, 'world');
+     * {hello: 'world'}
+     */
+    var dir = consoleFunc('dir');
+
+    /**
+     * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in
+     * the order of operations, the arguments `test` and `iteratee` are switched.
+     *
+     * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
+     *
+     * @name doWhilst
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.whilst]{@link module:ControlFlow.whilst}
+     * @category Control Flow
+     * @param {AsyncFunction} iteratee - A function which is called each time `test`
+     * passes. Invoked with (callback).
+     * @param {AsyncFunction} test - asynchronous truth test to perform after each
+     * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the
+     * non-error args from the previous callback of `iteratee`.
+     * @param {Function} [callback] - A callback which is called after the test
+     * function has failed and repeated execution of `iteratee` has stopped.
+     * `callback` will be passed an error and any arguments passed to the final
+     * `iteratee`'s callback. Invoked with (err, [results]);
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function doWhilst(iteratee, test, callback) {
+        callback = onlyOnce(callback);
+        var _fn = wrapAsync(iteratee);
+        var _test = wrapAsync(test);
+        var results;
+
+        function next(err, ...args) {
+            if (err) return callback(err);
+            if (err === false) return;
+            results = args;
+            _test(...args, check);
+        }
+
+        function check(err, truth) {
+            if (err) return callback(err);
+            if (err === false) return;
+            if (!truth) return callback(null, ...results);
+            _fn(next);
+        }
+
+        return check(null, true);
+    }
+
+    var doWhilst$1 = awaitify(doWhilst, 3);
+
+    /**
+     * Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the
+     * argument ordering differs from `until`.
+     *
+     * @name doUntil
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.doWhilst]{@link module:ControlFlow.doWhilst}
+     * @category Control Flow
+     * @param {AsyncFunction} iteratee - An async function which is called each time
+     * `test` fails. Invoked with (callback).
+     * @param {AsyncFunction} test - asynchronous truth test to perform after each
+     * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the
+     * non-error args from the previous callback of `iteratee`
+     * @param {Function} [callback] - A callback which is called after the test
+     * function has passed and repeated execution of `iteratee` has stopped. `callback`
+     * will be passed an error and any arguments passed to the final `iteratee`'s
+     * callback. Invoked with (err, [results]);
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function doUntil(iteratee, test, callback) {
+        const _test = wrapAsync(test);
+        return doWhilst$1(iteratee, (...args) => {
+            const cb = args.pop();
+            _test(...args, (err, truth) => cb (err, !truth));
+        }, callback);
+    }
+
+    function _withoutIndex(iteratee) {
+        return (value, index, callback) => iteratee(value, callback);
+    }
+
+    /**
+     * Applies the function `iteratee` to each item in `coll`, in parallel.
+     * The `iteratee` is called with an item from the list, and a callback for when
+     * it has finished. If the `iteratee` passes an error to its `callback`, the
+     * main `callback` (for the `each` function) is immediately called with the
+     * error.
+     *
+     * Note, that since this function applies `iteratee` to each item in parallel,
+     * there is no guarantee that the iteratee functions will complete in order.
+     *
+     * @name each
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @alias forEach
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async function to apply to
+     * each item in `coll`. Invoked with (item, callback).
+     * The array index is not passed to the iteratee.
+     * If you need the index, use `eachOf`.
+     * @param {Function} [callback] - A callback which is called when all
+     * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+     * @returns {Promise} a promise, if a callback is omitted
+     * @example
+     *
+     * // dir1 is a directory that contains file1.txt, file2.txt
+     * // dir2 is a directory that contains file3.txt, file4.txt
+     * // dir3 is a directory that contains file5.txt
+     * // dir4 does not exist
+     *
+     * const fileList = [ 'dir1/file2.txt', 'dir2/file3.txt', 'dir/file5.txt'];
+     * const withMissingFileList = ['dir1/file1.txt', 'dir4/file2.txt'];
+     *
+     * // asynchronous function that deletes a file
+     * const deleteFile = function(file, callback) {
+     *     fs.unlink(file, callback);
+     * };
+     *
+     * // Using callbacks
+     * async.each(fileList, deleteFile, function(err) {
+     *     if( err ) {
+     *         console.log(err);
+     *     } else {
+     *         console.log('All files have been deleted successfully');
+     *     }
+     * });
+     *
+     * // Error Handling
+     * async.each(withMissingFileList, deleteFile, function(err){
+     *     console.log(err);
+     *     // [ Error: ENOENT: no such file or directory ]
+     *     // since dir4/file2.txt does not exist
+     *     // dir1/file1.txt could have been deleted
+     * });
+     *
+     * // Using Promises
+     * async.each(fileList, deleteFile)
+     * .then( () => {
+     *     console.log('All files have been deleted successfully');
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * // Error Handling
+     * async.each(fileList, deleteFile)
+     * .then( () => {
+     *     console.log('All files have been deleted successfully');
+     * }).catch( err => {
+     *     console.log(err);
+     *     // [ Error: ENOENT: no such file or directory ]
+     *     // since dir4/file2.txt does not exist
+     *     // dir1/file1.txt could have been deleted
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         await async.each(files, deleteFile);
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * // Error Handling
+     * async () => {
+     *     try {
+     *         await async.each(withMissingFileList, deleteFile);
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *         // [ Error: ENOENT: no such file or directory ]
+     *         // since dir4/file2.txt does not exist
+     *         // dir1/file1.txt could have been deleted
+     *     }
+     * }
+     *
+     */
+    function eachLimit(coll, iteratee, callback) {
+        return eachOf$1(coll, _withoutIndex(wrapAsync(iteratee)), callback);
+    }
+
+    var each = awaitify(eachLimit, 3);
+
+    /**
+     * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time.
+     *
+     * @name eachLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.each]{@link module:Collections.each}
+     * @alias forEachLimit
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - An async function to apply to each item in
+     * `coll`.
+     * The array index is not passed to the iteratee.
+     * If you need the index, use `eachOfLimit`.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called when all
+     * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+     * @returns {Promise} a promise, if a callback is omitted
+     */
+    function eachLimit$1(coll, limit, iteratee, callback) {
+        return eachOfLimit(limit)(coll, _withoutIndex(wrapAsync(iteratee)), callback);
+    }
+    var eachLimit$2 = awaitify(eachLimit$1, 4);
+
+    /**
+     * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time.
+     *
+     * Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item
+     * in series and therefore the iteratee functions will complete in order.
+
+     * @name eachSeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.each]{@link module:Collections.each}
+     * @alias forEachSeries
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async function to apply to each
+     * item in `coll`.
+     * The array index is not passed to the iteratee.
+     * If you need the index, use `eachOfSeries`.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called when all
+     * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+     * @returns {Promise} a promise, if a callback is omitted
+     */
+    function eachSeries(coll, iteratee, callback) {
+        return eachLimit$2(coll, 1, iteratee, callback)
+    }
+    var eachSeries$1 = awaitify(eachSeries, 3);
+
+    /**
+     * Wrap an async function and ensure it calls its callback on a later tick of
+     * the event loop.  If the function already calls its callback on a next tick,
+     * no extra deferral is added. This is useful for preventing stack overflows
+     * (`RangeError: Maximum call stack size exceeded`) and generally keeping
+     * [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony)
+     * contained. ES2017 `async` functions are returned as-is -- they are immune
+     * to Zalgo's corrupting influences, as they always resolve on a later tick.
+     *
+     * @name ensureAsync
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @category Util
+     * @param {AsyncFunction} fn - an async function, one that expects a node-style
+     * callback as its last argument.
+     * @returns {AsyncFunction} Returns a wrapped function with the exact same call
+     * signature as the function passed in.
+     * @example
+     *
+     * function sometimesAsync(arg, callback) {
+     *     if (cache[arg]) {
+     *         return callback(null, cache[arg]); // this would be synchronous!!
+     *     } else {
+     *         doSomeIO(arg, callback); // this IO would be asynchronous
+     *     }
+     * }
+     *
+     * // this has a risk of stack overflows if many results are cached in a row
+     * async.mapSeries(args, sometimesAsync, done);
+     *
+     * // this will defer sometimesAsync's callback if necessary,
+     * // preventing stack overflows
+     * async.mapSeries(args, async.ensureAsync(sometimesAsync), done);
+     */
+    function ensureAsync(fn) {
+        if (isAsync(fn)) return fn;
+        return function (...args/*, callback*/) {
+            var callback = args.pop();
+            var sync = true;
+            args.push((...innerArgs) => {
+                if (sync) {
+                    setImmediate$1(() => callback(...innerArgs));
+                } else {
+                    callback(...innerArgs);
+                }
+            });
+            fn.apply(this, args);
+            sync = false;
+        };
+    }
+
+    /**
+     * Returns `true` if every element in `coll` satisfies an async test. If any
+     * iteratee call returns `false`, the main `callback` is immediately called.
+     *
+     * @name every
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @alias all
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+     * in the collection in parallel.
+     * The iteratee must complete with a boolean result value.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Result will be either `true` or `false`
+     * depending on the values of the async tests. Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback provided
+     * @example
+     *
+     * // dir1 is a directory that contains file1.txt, file2.txt
+     * // dir2 is a directory that contains file3.txt, file4.txt
+     * // dir3 is a directory that contains file5.txt
+     * // dir4 does not exist
+     *
+     * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file5.txt'];
+     * const withMissingFileList = ['file1.txt','file2.txt','file4.txt'];
+     *
+     * // asynchronous function that checks if a file exists
+     * function fileExists(file, callback) {
+     *    fs.access(file, fs.constants.F_OK, (err) => {
+     *        callback(null, !err);
+     *    });
+     * }
+     *
+     * // Using callbacks
+     * async.every(fileList, fileExists, function(err, result) {
+     *     console.log(result);
+     *     // true
+     *     // result is true since every file exists
+     * });
+     *
+     * async.every(withMissingFileList, fileExists, function(err, result) {
+     *     console.log(result);
+     *     // false
+     *     // result is false since NOT every file exists
+     * });
+     *
+     * // Using Promises
+     * async.every(fileList, fileExists)
+     * .then( result => {
+     *     console.log(result);
+     *     // true
+     *     // result is true since every file exists
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * async.every(withMissingFileList, fileExists)
+     * .then( result => {
+     *     console.log(result);
+     *     // false
+     *     // result is false since NOT every file exists
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let result = await async.every(fileList, fileExists);
+     *         console.log(result);
+     *         // true
+     *         // result is true since every file exists
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * async () => {
+     *     try {
+     *         let result = await async.every(withMissingFileList, fileExists);
+     *         console.log(result);
+     *         // false
+     *         // result is false since NOT every file exists
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function every(coll, iteratee, callback) {
+        return _createTester(bool => !bool, res => !res)(eachOf$1, coll, iteratee, callback)
+    }
+    var every$1 = awaitify(every, 3);
+
+    /**
+     * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time.
+     *
+     * @name everyLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.every]{@link module:Collections.every}
+     * @alias allLimit
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+     * in the collection in parallel.
+     * The iteratee must complete with a boolean result value.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Result will be either `true` or `false`
+     * depending on the values of the async tests. Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback provided
+     */
+    function everyLimit(coll, limit, iteratee, callback) {
+        return _createTester(bool => !bool, res => !res)(eachOfLimit(limit), coll, iteratee, callback)
+    }
+    var everyLimit$1 = awaitify(everyLimit, 4);
+
+    /**
+     * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time.
+     *
+     * @name everySeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.every]{@link module:Collections.every}
+     * @alias allSeries
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+     * in the collection in series.
+     * The iteratee must complete with a boolean result value.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Result will be either `true` or `false`
+     * depending on the values of the async tests. Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback provided
+     */
+    function everySeries(coll, iteratee, callback) {
+        return _createTester(bool => !bool, res => !res)(eachOfSeries$1, coll, iteratee, callback)
+    }
+    var everySeries$1 = awaitify(everySeries, 3);
+
+    function filterArray(eachfn, arr, iteratee, callback) {
+        var truthValues = new Array(arr.length);
+        eachfn(arr, (x, index, iterCb) => {
+            iteratee(x, (err, v) => {
+                truthValues[index] = !!v;
+                iterCb(err);
+            });
+        }, err => {
+            if (err) return callback(err);
+            var results = [];
+            for (var i = 0; i < arr.length; i++) {
+                if (truthValues[i]) results.push(arr[i]);
+            }
+            callback(null, results);
+        });
+    }
+
+    function filterGeneric(eachfn, coll, iteratee, callback) {
+        var results = [];
+        eachfn(coll, (x, index, iterCb) => {
+            iteratee(x, (err, v) => {
+                if (err) return iterCb(err);
+                if (v) {
+                    results.push({index, value: x});
+                }
+                iterCb(err);
+            });
+        }, err => {
+            if (err) return callback(err);
+            callback(null, results
+                .sort((a, b) => a.index - b.index)
+                .map(v => v.value));
+        });
+    }
+
+    function _filter(eachfn, coll, iteratee, callback) {
+        var filter = isArrayLike(coll) ? filterArray : filterGeneric;
+        return filter(eachfn, coll, wrapAsync(iteratee), callback);
+    }
+
+    /**
+     * Returns a new array of all the values in `coll` which pass an async truth
+     * test. This operation is performed in parallel, but the results array will be
+     * in the same order as the original.
+     *
+     * @name filter
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @alias select
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+     * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+     * with a boolean argument once it has completed. Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Invoked with (err, results).
+     * @returns {Promise} a promise, if no callback provided
+     * @example
+     *
+     * // dir1 is a directory that contains file1.txt, file2.txt
+     * // dir2 is a directory that contains file3.txt, file4.txt
+     * // dir3 is a directory that contains file5.txt
+     *
+     * const files = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt'];
+     *
+     * // asynchronous function that checks if a file exists
+     * function fileExists(file, callback) {
+     *    fs.access(file, fs.constants.F_OK, (err) => {
+     *        callback(null, !err);
+     *    });
+     * }
+     *
+     * // Using callbacks
+     * async.filter(files, fileExists, function(err, results) {
+     *    if(err) {
+     *        console.log(err);
+     *    } else {
+     *        console.log(results);
+     *        // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+     *        // results is now an array of the existing files
+     *    }
+     * });
+     *
+     * // Using Promises
+     * async.filter(files, fileExists)
+     * .then(results => {
+     *     console.log(results);
+     *     // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+     *     // results is now an array of the existing files
+     * }).catch(err => {
+     *     console.log(err);
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let results = await async.filter(files, fileExists);
+     *         console.log(results);
+     *         // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+     *         // results is now an array of the existing files
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function filter (coll, iteratee, callback) {
+        return _filter(eachOf$1, coll, iteratee, callback)
+    }
+    var filter$1 = awaitify(filter, 3);
+
+    /**
+     * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a
+     * time.
+     *
+     * @name filterLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.filter]{@link module:Collections.filter}
+     * @alias selectLimit
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+     * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+     * with a boolean argument once it has completed. Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Invoked with (err, results).
+     * @returns {Promise} a promise, if no callback provided
+     */
+    function filterLimit (coll, limit, iteratee, callback) {
+        return _filter(eachOfLimit(limit), coll, iteratee, callback)
+    }
+    var filterLimit$1 = awaitify(filterLimit, 4);
+
+    /**
+     * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time.
+     *
+     * @name filterSeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.filter]{@link module:Collections.filter}
+     * @alias selectSeries
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+     * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+     * with a boolean argument once it has completed. Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Invoked with (err, results)
+     * @returns {Promise} a promise, if no callback provided
+     */
+    function filterSeries (coll, iteratee, callback) {
+        return _filter(eachOfSeries$1, coll, iteratee, callback)
+    }
+    var filterSeries$1 = awaitify(filterSeries, 3);
+
+    /**
+     * Calls the asynchronous function `fn` with a callback parameter that allows it
+     * to call itself again, in series, indefinitely.
+
+     * If an error is passed to the callback then `errback` is called with the
+     * error, and execution stops, otherwise it will never be called.
+     *
+     * @name forever
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {AsyncFunction} fn - an async function to call repeatedly.
+     * Invoked with (next).
+     * @param {Function} [errback] - when `fn` passes an error to it's callback,
+     * this function will be called, and execution stops. Invoked with (err).
+     * @returns {Promise} a promise that rejects if an error occurs and an errback
+     * is not passed
+     * @example
+     *
+     * async.forever(
+     *     function(next) {
+     *         // next is suitable for passing to things that need a callback(err [, whatever]);
+     *         // it will result in this function being called again.
+     *     },
+     *     function(err) {
+     *         // if next is called with a value in its first parameter, it will appear
+     *         // in here as 'err', and execution will stop.
+     *     }
+     * );
+     */
+    function forever(fn, errback) {
+        var done = onlyOnce(errback);
+        var task = wrapAsync(ensureAsync(fn));
+
+        function next(err) {
+            if (err) return done(err);
+            if (err === false) return;
+            task(next);
+        }
+        return next();
+    }
+    var forever$1 = awaitify(forever, 2);
+
+    /**
+     * The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time.
+     *
+     * @name groupByLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.groupBy]{@link module:Collections.groupBy}
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - An async function to apply to each item in
+     * `coll`.
+     * The iteratee should complete with a `key` to group the value under.
+     * Invoked with (value, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. Result is an `Object` whoses
+     * properties are arrays of values which returned the corresponding key.
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function groupByLimit(coll, limit, iteratee, callback) {
+        var _iteratee = wrapAsync(iteratee);
+        return mapLimit$1(coll, limit, (val, iterCb) => {
+            _iteratee(val, (err, key) => {
+                if (err) return iterCb(err);
+                return iterCb(err, {key, val});
+            });
+        }, (err, mapResults) => {
+            var result = {};
+            // from MDN, handle object having an `hasOwnProperty` prop
+            var {hasOwnProperty} = Object.prototype;
+
+            for (var i = 0; i < mapResults.length; i++) {
+                if (mapResults[i]) {
+                    var {key} = mapResults[i];
+                    var {val} = mapResults[i];
+
+                    if (hasOwnProperty.call(result, key)) {
+                        result[key].push(val);
+                    } else {
+                        result[key] = [val];
+                    }
+                }
+            }
+
+            return callback(err, result);
+        });
+    }
+
+    var groupByLimit$1 = awaitify(groupByLimit, 4);
+
+    /**
+     * Returns a new object, where each value corresponds to an array of items, from
+     * `coll`, that returned the corresponding key. That is, the keys of the object
+     * correspond to the values passed to the `iteratee` callback.
+     *
+     * Note: Since this function applies the `iteratee` to each item in parallel,
+     * there is no guarantee that the `iteratee` functions will complete in order.
+     * However, the values for each key in the `result` will be in the same order as
+     * the original `coll`. For Objects, the values will roughly be in the order of
+     * the original Objects' keys (but this can vary across JavaScript engines).
+     *
+     * @name groupBy
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async function to apply to each item in
+     * `coll`.
+     * The iteratee should complete with a `key` to group the value under.
+     * Invoked with (value, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. Result is an `Object` whoses
+     * properties are arrays of values which returned the corresponding key.
+     * @returns {Promise} a promise, if no callback is passed
+     * @example
+     *
+     * // dir1 is a directory that contains file1.txt, file2.txt
+     * // dir2 is a directory that contains file3.txt, file4.txt
+     * // dir3 is a directory that contains file5.txt
+     * // dir4 does not exist
+     *
+     * const files = ['dir1/file1.txt','dir2','dir4']
+     *
+     * // asynchronous function that detects file type as none, file, or directory
+     * function detectFile(file, callback) {
+     *     fs.stat(file, function(err, stat) {
+     *         if (err) {
+     *             return callback(null, 'none');
+     *         }
+     *         callback(null, stat.isDirectory() ? 'directory' : 'file');
+     *     });
+     * }
+     *
+     * //Using callbacks
+     * async.groupBy(files, detectFile, function(err, result) {
+     *     if(err) {
+     *         console.log(err);
+     *     } else {
+     *	       console.log(result);
+     *         // {
+     *         //     file: [ 'dir1/file1.txt' ],
+     *         //     none: [ 'dir4' ],
+     *         //     directory: [ 'dir2']
+     *         // }
+     *         // result is object containing the files grouped by type
+     *     }
+     * });
+     *
+     * // Using Promises
+     * async.groupBy(files, detectFile)
+     * .then( result => {
+     *     console.log(result);
+     *     // {
+     *     //     file: [ 'dir1/file1.txt' ],
+     *     //     none: [ 'dir4' ],
+     *     //     directory: [ 'dir2']
+     *     // }
+     *     // result is object containing the files grouped by type
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let result = await async.groupBy(files, detectFile);
+     *         console.log(result);
+     *         // {
+     *         //     file: [ 'dir1/file1.txt' ],
+     *         //     none: [ 'dir4' ],
+     *         //     directory: [ 'dir2']
+     *         // }
+     *         // result is object containing the files grouped by type
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function groupBy (coll, iteratee, callback) {
+        return groupByLimit$1(coll, Infinity, iteratee, callback)
+    }
+
+    /**
+     * The same as [`groupBy`]{@link module:Collections.groupBy} but runs only a single async operation at a time.
+     *
+     * @name groupBySeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.groupBy]{@link module:Collections.groupBy}
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async function to apply to each item in
+     * `coll`.
+     * The iteratee should complete with a `key` to group the value under.
+     * Invoked with (value, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. Result is an `Object` whose
+     * properties are arrays of values which returned the corresponding key.
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function groupBySeries (coll, iteratee, callback) {
+        return groupByLimit$1(coll, 1, iteratee, callback)
+    }
+
+    /**
+     * Logs the result of an `async` function to the `console`. Only works in
+     * Node.js or in browsers that support `console.log` and `console.error` (such
+     * as FF and Chrome). If multiple arguments are returned from the async
+     * function, `console.log` is called on each argument in order.
+     *
+     * @name log
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @category Util
+     * @param {AsyncFunction} function - The function you want to eventually apply
+     * all arguments to.
+     * @param {...*} arguments... - Any number of arguments to apply to the function.
+     * @example
+     *
+     * // in a module
+     * var hello = function(name, callback) {
+     *     setTimeout(function() {
+     *         callback(null, 'hello ' + name);
+     *     }, 1000);
+     * };
+     *
+     * // in the node repl
+     * node> async.log(hello, 'world');
+     * 'hello world'
+     */
+    var log = consoleFunc('log');
+
+    /**
+     * The same as [`mapValues`]{@link module:Collections.mapValues} but runs a maximum of `limit` async operations at a
+     * time.
+     *
+     * @name mapValuesLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.mapValues]{@link module:Collections.mapValues}
+     * @category Collection
+     * @param {Object} obj - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - A function to apply to each value and key
+     * in `coll`.
+     * The iteratee should complete with the transformed value as its result.
+     * Invoked with (value, key, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. `result` is a new object consisting
+     * of each key from `obj`, with each transformed value on the right-hand side.
+     * Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function mapValuesLimit(obj, limit, iteratee, callback) {
+        callback = once(callback);
+        var newObj = {};
+        var _iteratee = wrapAsync(iteratee);
+        return eachOfLimit(limit)(obj, (val, key, next) => {
+            _iteratee(val, key, (err, result) => {
+                if (err) return next(err);
+                newObj[key] = result;
+                next(err);
+            });
+        }, err => callback(err, newObj));
+    }
+
+    var mapValuesLimit$1 = awaitify(mapValuesLimit, 4);
+
+    /**
+     * A relative of [`map`]{@link module:Collections.map}, designed for use with objects.
+     *
+     * Produces a new Object by mapping each value of `obj` through the `iteratee`
+     * function. The `iteratee` is called each `value` and `key` from `obj` and a
+     * callback for when it has finished processing. Each of these callbacks takes
+     * two arguments: an `error`, and the transformed item from `obj`. If `iteratee`
+     * passes an error to its callback, the main `callback` (for the `mapValues`
+     * function) is immediately called with the error.
+     *
+     * Note, the order of the keys in the result is not guaranteed.  The keys will
+     * be roughly in the order they complete, (but this is very engine-specific)
+     *
+     * @name mapValues
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @category Collection
+     * @param {Object} obj - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - A function to apply to each value and key
+     * in `coll`.
+     * The iteratee should complete with the transformed value as its result.
+     * Invoked with (value, key, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. `result` is a new object consisting
+     * of each key from `obj`, with each transformed value on the right-hand side.
+     * Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback is passed
+     * @example
+     *
+     * // file1.txt is a file that is 1000 bytes in size
+     * // file2.txt is a file that is 2000 bytes in size
+     * // file3.txt is a file that is 3000 bytes in size
+     * // file4.txt does not exist
+     *
+     * const fileMap = {
+     *     f1: 'file1.txt',
+     *     f2: 'file2.txt',
+     *     f3: 'file3.txt'
+     * };
+     *
+     * const withMissingFileMap = {
+     *     f1: 'file1.txt',
+     *     f2: 'file2.txt',
+     *     f3: 'file4.txt'
+     * };
+     *
+     * // asynchronous function that returns the file size in bytes
+     * function getFileSizeInBytes(file, key, callback) {
+     *     fs.stat(file, function(err, stat) {
+     *         if (err) {
+     *             return callback(err);
+     *         }
+     *         callback(null, stat.size);
+     *     });
+     * }
+     *
+     * // Using callbacks
+     * async.mapValues(fileMap, getFileSizeInBytes, function(err, result) {
+     *     if (err) {
+     *         console.log(err);
+     *     } else {
+     *         console.log(result);
+     *         // result is now a map of file size in bytes for each file, e.g.
+     *         // {
+     *         //     f1: 1000,
+     *         //     f2: 2000,
+     *         //     f3: 3000
+     *         // }
+     *     }
+     * });
+     *
+     * // Error handling
+     * async.mapValues(withMissingFileMap, getFileSizeInBytes, function(err, result) {
+     *     if (err) {
+     *         console.log(err);
+     *         // [ Error: ENOENT: no such file or directory ]
+     *     } else {
+     *         console.log(result);
+     *     }
+     * });
+     *
+     * // Using Promises
+     * async.mapValues(fileMap, getFileSizeInBytes)
+     * .then( result => {
+     *     console.log(result);
+     *     // result is now a map of file size in bytes for each file, e.g.
+     *     // {
+     *     //     f1: 1000,
+     *     //     f2: 2000,
+     *     //     f3: 3000
+     *     // }
+     * }).catch (err => {
+     *     console.log(err);
+     * });
+     *
+     * // Error Handling
+     * async.mapValues(withMissingFileMap, getFileSizeInBytes)
+     * .then( result => {
+     *     console.log(result);
+     * }).catch (err => {
+     *     console.log(err);
+     *     // [ Error: ENOENT: no such file or directory ]
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let result = await async.mapValues(fileMap, getFileSizeInBytes);
+     *         console.log(result);
+     *         // result is now a map of file size in bytes for each file, e.g.
+     *         // {
+     *         //     f1: 1000,
+     *         //     f2: 2000,
+     *         //     f3: 3000
+     *         // }
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * // Error Handling
+     * async () => {
+     *     try {
+     *         let result = await async.mapValues(withMissingFileMap, getFileSizeInBytes);
+     *         console.log(result);
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *         // [ Error: ENOENT: no such file or directory ]
+     *     }
+     * }
+     *
+     */
+    function mapValues(obj, iteratee, callback) {
+        return mapValuesLimit$1(obj, Infinity, iteratee, callback)
+    }
+
+    /**
+     * The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time.
+     *
+     * @name mapValuesSeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.mapValues]{@link module:Collections.mapValues}
+     * @category Collection
+     * @param {Object} obj - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - A function to apply to each value and key
+     * in `coll`.
+     * The iteratee should complete with the transformed value as its result.
+     * Invoked with (value, key, callback).
+     * @param {Function} [callback] - A callback which is called when all `iteratee`
+     * functions have finished, or an error occurs. `result` is a new object consisting
+     * of each key from `obj`, with each transformed value on the right-hand side.
+     * Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function mapValuesSeries(obj, iteratee, callback) {
+        return mapValuesLimit$1(obj, 1, iteratee, callback)
+    }
+
+    /**
+     * Caches the results of an async function. When creating a hash to store
+     * function results against, the callback is omitted from the hash and an
+     * optional hash function can be used.
+     *
+     * **Note: if the async function errs, the result will not be cached and
+     * subsequent calls will call the wrapped function.**
+     *
+     * If no hash function is specified, the first argument is used as a hash key,
+     * which may work reasonably if it is a string or a data type that converts to a
+     * distinct string. Note that objects and arrays will not behave reasonably.
+     * Neither will cases where the other arguments are significant. In such cases,
+     * specify your own hash function.
+     *
+     * The cache of results is exposed as the `memo` property of the function
+     * returned by `memoize`.
+     *
+     * @name memoize
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @category Util
+     * @param {AsyncFunction} fn - The async function to proxy and cache results from.
+     * @param {Function} hasher - An optional function for generating a custom hash
+     * for storing results. It has all the arguments applied to it apart from the
+     * callback, and must be synchronous.
+     * @returns {AsyncFunction} a memoized version of `fn`
+     * @example
+     *
+     * var slow_fn = function(name, callback) {
+     *     // do something
+     *     callback(null, result);
+     * };
+     * var fn = async.memoize(slow_fn);
+     *
+     * // fn can now be used as if it were slow_fn
+     * fn('some name', function() {
+     *     // callback
+     * });
+     */
+    function memoize(fn, hasher = v => v) {
+        var memo = Object.create(null);
+        var queues = Object.create(null);
+        var _fn = wrapAsync(fn);
+        var memoized = initialParams((args, callback) => {
+            var key = hasher(...args);
+            if (key in memo) {
+                setImmediate$1(() => callback(null, ...memo[key]));
+            } else if (key in queues) {
+                queues[key].push(callback);
+            } else {
+                queues[key] = [callback];
+                _fn(...args, (err, ...resultArgs) => {
+                    // #1465 don't memoize if an error occurred
+                    if (!err) {
+                        memo[key] = resultArgs;
+                    }
+                    var q = queues[key];
+                    delete queues[key];
+                    for (var i = 0, l = q.length; i < l; i++) {
+                        q[i](err, ...resultArgs);
+                    }
+                });
+            }
+        });
+        memoized.memo = memo;
+        memoized.unmemoized = fn;
+        return memoized;
+    }
+
+    /* istanbul ignore file */
+
+    /**
+     * Calls `callback` on a later loop around the event loop. In Node.js this just
+     * calls `process.nextTick`.  In the browser it will use `setImmediate` if
+     * available, otherwise `setTimeout(callback, 0)`, which means other higher
+     * priority events may precede the execution of `callback`.
+     *
+     * This is used internally for browser-compatibility purposes.
+     *
+     * @name nextTick
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @see [async.setImmediate]{@link module:Utils.setImmediate}
+     * @category Util
+     * @param {Function} callback - The function to call on a later loop around
+     * the event loop. Invoked with (args...).
+     * @param {...*} args... - any number of additional arguments to pass to the
+     * callback on the next tick.
+     * @example
+     *
+     * var call_order = [];
+     * async.nextTick(function() {
+     *     call_order.push('two');
+     *     // call_order now equals ['one','two']
+     * });
+     * call_order.push('one');
+     *
+     * async.setImmediate(function (a, b, c) {
+     *     // a, b, and c equal 1, 2, and 3
+     * }, 1, 2, 3);
+     */
+    var _defer$1;
+
+    if (hasNextTick) {
+        _defer$1 = process.nextTick;
+    } else if (hasSetImmediate) {
+        _defer$1 = setImmediate;
+    } else {
+        _defer$1 = fallback;
+    }
+
+    var nextTick = wrap(_defer$1);
+
+    var parallel = awaitify((eachfn, tasks, callback) => {
+        var results = isArrayLike(tasks) ? [] : {};
+
+        eachfn(tasks, (task, key, taskCb) => {
+            wrapAsync(task)((err, ...result) => {
+                if (result.length < 2) {
+                    [result] = result;
+                }
+                results[key] = result;
+                taskCb(err);
+            });
+        }, err => callback(err, results));
+    }, 3);
+
+    /**
+     * Run the `tasks` collection of functions in parallel, without waiting until
+     * the previous function has completed. If any of the functions pass an error to
+     * its callback, the main `callback` is immediately called with the value of the
+     * error. Once the `tasks` have completed, the results are passed to the final
+     * `callback` as an array.
+     *
+     * **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about
+     * parallel execution of code.  If your tasks do not use any timers or perform
+     * any I/O, they will actually be executed in series.  Any synchronous setup
+     * sections for each task will happen one after the other.  JavaScript remains
+     * single-threaded.
+     *
+     * **Hint:** Use [`reflect`]{@link module:Utils.reflect} to continue the
+     * execution of other tasks when a task fails.
+     *
+     * It is also possible to use an object instead of an array. Each property will
+     * be run as a function and the results will be passed to the final `callback`
+     * as an object instead of an array. This can be a more readable way of handling
+     * results from {@link async.parallel}.
+     *
+     * @name parallel
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of
+     * [async functions]{@link AsyncFunction} to run.
+     * Each async function can complete with any number of optional `result` values.
+     * @param {Function} [callback] - An optional callback to run once all the
+     * functions have completed successfully. This function gets a results array
+     * (or object) containing all the result arguments passed to the task callbacks.
+     * Invoked with (err, results).
+     * @returns {Promise} a promise, if a callback is not passed
+     *
+     * @example
+     *
+     * //Using Callbacks
+     * async.parallel([
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'one');
+     *         }, 200);
+     *     },
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'two');
+     *         }, 100);
+     *     }
+     * ], function(err, results) {
+     *     console.log(results);
+     *     // results is equal to ['one','two'] even though
+     *     // the second function had a shorter timeout.
+     * });
+     *
+     * // an example using an object instead of an array
+     * async.parallel({
+     *     one: function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 1);
+     *         }, 200);
+     *     },
+     *     two: function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 2);
+     *         }, 100);
+     *     }
+     * }, function(err, results) {
+     *     console.log(results);
+     *     // results is equal to: { one: 1, two: 2 }
+     * });
+     *
+     * //Using Promises
+     * async.parallel([
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'one');
+     *         }, 200);
+     *     },
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'two');
+     *         }, 100);
+     *     }
+     * ]).then(results => {
+     *     console.log(results);
+     *     // results is equal to ['one','two'] even though
+     *     // the second function had a shorter timeout.
+     * }).catch(err => {
+     *     console.log(err);
+     * });
+     *
+     * // an example using an object instead of an array
+     * async.parallel({
+     *     one: function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 1);
+     *         }, 200);
+     *     },
+     *     two: function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 2);
+     *         }, 100);
+     *     }
+     * }).then(results => {
+     *     console.log(results);
+     *     // results is equal to: { one: 1, two: 2 }
+     * }).catch(err => {
+     *     console.log(err);
+     * });
+     *
+     * //Using async/await
+     * async () => {
+     *     try {
+     *         let results = await async.parallel([
+     *             function(callback) {
+     *                 setTimeout(function() {
+     *                     callback(null, 'one');
+     *                 }, 200);
+     *             },
+     *             function(callback) {
+     *                 setTimeout(function() {
+     *                     callback(null, 'two');
+     *                 }, 100);
+     *             }
+     *         ]);
+     *         console.log(results);
+     *         // results is equal to ['one','two'] even though
+     *         // the second function had a shorter timeout.
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * // an example using an object instead of an array
+     * async () => {
+     *     try {
+     *         let results = await async.parallel({
+     *             one: function(callback) {
+     *                 setTimeout(function() {
+     *                     callback(null, 1);
+     *                 }, 200);
+     *             },
+     *            two: function(callback) {
+     *                 setTimeout(function() {
+     *                     callback(null, 2);
+     *                 }, 100);
+     *            }
+     *         });
+     *         console.log(results);
+     *         // results is equal to: { one: 1, two: 2 }
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function parallel$1(tasks, callback) {
+        return parallel(eachOf$1, tasks, callback);
+    }
+
+    /**
+     * The same as [`parallel`]{@link module:ControlFlow.parallel} but runs a maximum of `limit` async operations at a
+     * time.
+     *
+     * @name parallelLimit
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.parallel]{@link module:ControlFlow.parallel}
+     * @category Control Flow
+     * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of
+     * [async functions]{@link AsyncFunction} to run.
+     * Each async function can complete with any number of optional `result` values.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {Function} [callback] - An optional callback to run once all the
+     * functions have completed successfully. This function gets a results array
+     * (or object) containing all the result arguments passed to the task callbacks.
+     * Invoked with (err, results).
+     * @returns {Promise} a promise, if a callback is not passed
+     */
+    function parallelLimit(tasks, limit, callback) {
+        return parallel(eachOfLimit(limit), tasks, callback);
+    }
+
+    /**
+     * A queue of tasks for the worker function to complete.
+     * @typedef {Iterable} QueueObject
+     * @memberOf module:ControlFlow
+     * @property {Function} length - a function returning the number of items
+     * waiting to be processed. Invoke with `queue.length()`.
+     * @property {boolean} started - a boolean indicating whether or not any
+     * items have been pushed and processed by the queue.
+     * @property {Function} running - a function returning the number of items
+     * currently being processed. Invoke with `queue.running()`.
+     * @property {Function} workersList - a function returning the array of items
+     * currently being processed. Invoke with `queue.workersList()`.
+     * @property {Function} idle - a function returning false if there are items
+     * waiting or being processed, or true if not. Invoke with `queue.idle()`.
+     * @property {number} concurrency - an integer for determining how many `worker`
+     * functions should be run in parallel. This property can be changed after a
+     * `queue` is created to alter the concurrency on-the-fly.
+     * @property {number} payload - an integer that specifies how many items are
+     * passed to the worker function at a time. only applies if this is a
+     * [cargo]{@link module:ControlFlow.cargo} object
+     * @property {AsyncFunction} push - add a new task to the `queue`. Calls `callback`
+     * once the `worker` has finished processing the task. Instead of a single task,
+     * a `tasks` array can be submitted. The respective callback is used for every
+     * task in the list. Invoke with `queue.push(task, [callback])`,
+     * @property {AsyncFunction} unshift - add a new task to the front of the `queue`.
+     * Invoke with `queue.unshift(task, [callback])`.
+     * @property {AsyncFunction} pushAsync - the same as `q.push`, except this returns
+     * a promise that rejects if an error occurs.
+     * @property {AsyncFunction} unshiftAsync - the same as `q.unshift`, except this returns
+     * a promise that rejects if an error occurs.
+     * @property {Function} remove - remove items from the queue that match a test
+     * function.  The test function will be passed an object with a `data` property,
+     * and a `priority` property, if this is a
+     * [priorityQueue]{@link module:ControlFlow.priorityQueue} object.
+     * Invoked with `queue.remove(testFn)`, where `testFn` is of the form
+     * `function ({data, priority}) {}` and returns a Boolean.
+     * @property {Function} saturated - a function that sets a callback that is
+     * called when the number of running workers hits the `concurrency` limit, and
+     * further tasks will be queued.  If the callback is omitted, `q.saturated()`
+     * returns a promise for the next occurrence.
+     * @property {Function} unsaturated - a function that sets a callback that is
+     * called when the number of running workers is less than the `concurrency` &
+     * `buffer` limits, and further tasks will not be queued. If the callback is
+     * omitted, `q.unsaturated()` returns a promise for the next occurrence.
+     * @property {number} buffer - A minimum threshold buffer in order to say that
+     * the `queue` is `unsaturated`.
+     * @property {Function} empty - a function that sets a callback that is called
+     * when the last item from the `queue` is given to a `worker`. If the callback
+     * is omitted, `q.empty()` returns a promise for the next occurrence.
+     * @property {Function} drain - a function that sets a callback that is called
+     * when the last item from the `queue` has returned from the `worker`. If the
+     * callback is omitted, `q.drain()` returns a promise for the next occurrence.
+     * @property {Function} error - a function that sets a callback that is called
+     * when a task errors. Has the signature `function(error, task)`. If the
+     * callback is omitted, `error()` returns a promise that rejects on the next
+     * error.
+     * @property {boolean} paused - a boolean for determining whether the queue is
+     * in a paused state.
+     * @property {Function} pause - a function that pauses the processing of tasks
+     * until `resume()` is called. Invoke with `queue.pause()`.
+     * @property {Function} resume - a function that resumes the processing of
+     * queued tasks when the queue is paused. Invoke with `queue.resume()`.
+     * @property {Function} kill - a function that removes the `drain` callback and
+     * empties remaining tasks from the queue forcing it to go idle. No more tasks
+     * should be pushed to the queue after calling this function. Invoke with `queue.kill()`.
+     *
+     * @example
+     * const q = async.queue(worker, 2)
+     * q.push(item1)
+     * q.push(item2)
+     * q.push(item3)
+     * // queues are iterable, spread into an array to inspect
+     * const items = [...q] // [item1, item2, item3]
+     * // or use for of
+     * for (let item of q) {
+     *     console.log(item)
+     * }
+     *
+     * q.drain(() => {
+     *     console.log('all done')
+     * })
+     * // or
+     * await q.drain()
+     */
+
+    /**
+     * Creates a `queue` object with the specified `concurrency`. Tasks added to the
+     * `queue` are processed in parallel (up to the `concurrency` limit). If all
+     * `worker`s are in progress, the task is queued until one becomes available.
+     * Once a `worker` completes a `task`, that `task`'s callback is called.
+     *
+     * @name queue
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {AsyncFunction} worker - An async function for processing a queued task.
+     * If you want to handle errors from an individual task, pass a callback to
+     * `q.push()`. Invoked with (task, callback).
+     * @param {number} [concurrency=1] - An `integer` for determining how many
+     * `worker` functions should be run in parallel.  If omitted, the concurrency
+     * defaults to `1`.  If the concurrency is `0`, an error is thrown.
+     * @returns {module:ControlFlow.QueueObject} A queue object to manage the tasks. Callbacks can be
+     * attached as certain properties to listen for specific events during the
+     * lifecycle of the queue.
+     * @example
+     *
+     * // create a queue object with concurrency 2
+     * var q = async.queue(function(task, callback) {
+     *     console.log('hello ' + task.name);
+     *     callback();
+     * }, 2);
+     *
+     * // assign a callback
+     * q.drain(function() {
+     *     console.log('all items have been processed');
+     * });
+     * // or await the end
+     * await q.drain()
+     *
+     * // assign an error callback
+     * q.error(function(err, task) {
+     *     console.error('task experienced an error');
+     * });
+     *
+     * // add some items to the queue
+     * q.push({name: 'foo'}, function(err) {
+     *     console.log('finished processing foo');
+     * });
+     * // callback is optional
+     * q.push({name: 'bar'});
+     *
+     * // add some items to the queue (batch-wise)
+     * q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
+     *     console.log('finished processing item');
+     * });
+     *
+     * // add some items to the front of the queue
+     * q.unshift({name: 'bar'}, function (err) {
+     *     console.log('finished processing bar');
+     * });
+     */
+    function queue$1 (worker, concurrency) {
+        var _worker = wrapAsync(worker);
+        return queue((items, cb) => {
+            _worker(items[0], cb);
+        }, concurrency, 1);
+    }
+
+    // Binary min-heap implementation used for priority queue.
+    // Implementation is stable, i.e. push time is considered for equal priorities
+    class Heap {
+        constructor() {
+            this.heap = [];
+            this.pushCount = Number.MIN_SAFE_INTEGER;
+        }
+
+        get length() {
+            return this.heap.length;
+        }
+
+        empty () {
+            this.heap = [];
+            return this;
+        }
+
+        percUp(index) {
+            let p;
+
+            while (index > 0 && smaller(this.heap[index], this.heap[p=parent(index)])) {
+                let t = this.heap[index];
+                this.heap[index] = this.heap[p];
+                this.heap[p] = t;
+
+                index = p;
+            }
+        }
+
+        percDown(index) {
+            let l;
+
+            while ((l=leftChi(index)) < this.heap.length) {
+                if (l+1 < this.heap.length && smaller(this.heap[l+1], this.heap[l])) {
+                    l = l+1;
+                }
+
+                if (smaller(this.heap[index], this.heap[l])) {
+                    break;
+                }
+
+                let t = this.heap[index];
+                this.heap[index] = this.heap[l];
+                this.heap[l] = t;
+
+                index = l;
+            }
+        }
+
+        push(node) {
+            node.pushCount = ++this.pushCount;
+            this.heap.push(node);
+            this.percUp(this.heap.length-1);
+        }
+
+        unshift(node) {
+            return this.heap.push(node);
+        }
+
+        shift() {
+            let [top] = this.heap;
+
+            this.heap[0] = this.heap[this.heap.length-1];
+            this.heap.pop();
+            this.percDown(0);
+
+            return top;
+        }
+
+        toArray() {
+            return [...this];
+        }
+
+        *[Symbol.iterator] () {
+            for (let i = 0; i < this.heap.length; i++) {
+                yield this.heap[i].data;
+            }
+        }
+
+        remove (testFn) {
+            let j = 0;
+            for (let i = 0; i < this.heap.length; i++) {
+                if (!testFn(this.heap[i])) {
+                    this.heap[j] = this.heap[i];
+                    j++;
+                }
+            }
+
+            this.heap.splice(j);
+
+            for (let i = parent(this.heap.length-1); i >= 0; i--) {
+                this.percDown(i);
+            }
+
+            return this;
+        }
+    }
+
+    function leftChi(i) {
+        return (i<<1)+1;
+    }
+
+    function parent(i) {
+        return ((i+1)>>1)-1;
+    }
+
+    function smaller(x, y) {
+        if (x.priority !== y.priority) {
+            return x.priority < y.priority;
+        }
+        else {
+            return x.pushCount < y.pushCount;
+        }
+    }
+
+    /**
+     * The same as [async.queue]{@link module:ControlFlow.queue} only tasks are assigned a priority and
+     * completed in ascending priority order.
+     *
+     * @name priorityQueue
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.queue]{@link module:ControlFlow.queue}
+     * @category Control Flow
+     * @param {AsyncFunction} worker - An async function for processing a queued task.
+     * If you want to handle errors from an individual task, pass a callback to
+     * `q.push()`.
+     * Invoked with (task, callback).
+     * @param {number} concurrency - An `integer` for determining how many `worker`
+     * functions should be run in parallel.  If omitted, the concurrency defaults to
+     * `1`.  If the concurrency is `0`, an error is thrown.
+     * @returns {module:ControlFlow.QueueObject} A priorityQueue object to manage the tasks. There are three
+     * differences between `queue` and `priorityQueue` objects:
+     * * `push(task, priority, [callback])` - `priority` should be a number. If an
+     *   array of `tasks` is given, all tasks will be assigned the same priority.
+     * * `pushAsync(task, priority, [callback])` - the same as `priorityQueue.push`,
+     *   except this returns a promise that rejects if an error occurs.
+     * * The `unshift` and `unshiftAsync` methods were removed.
+     */
+    function priorityQueue(worker, concurrency) {
+        // Start with a normal queue
+        var q = queue$1(worker, concurrency);
+
+        var {
+            push,
+            pushAsync
+        } = q;
+
+        q._tasks = new Heap();
+        q._createTaskItem = ({data, priority}, callback) => {
+            return {
+                data,
+                priority,
+                callback
+            };
+        };
+
+        function createDataItems(tasks, priority) {
+            if (!Array.isArray(tasks)) {
+                return {data: tasks, priority};
+            }
+            return tasks.map(data => { return {data, priority}; });
+        }
+
+        // Override push to accept second parameter representing priority
+        q.push = function(data, priority = 0, callback) {
+            return push(createDataItems(data, priority), callback);
+        };
+
+        q.pushAsync = function(data, priority = 0, callback) {
+            return pushAsync(createDataItems(data, priority), callback);
+        };
+
+        // Remove unshift functions
+        delete q.unshift;
+        delete q.unshiftAsync;
+
+        return q;
+    }
+
+    /**
+     * Runs the `tasks` array of functions in parallel, without waiting until the
+     * previous function has completed. Once any of the `tasks` complete or pass an
+     * error to its callback, the main `callback` is immediately called. It's
+     * equivalent to `Promise.race()`.
+     *
+     * @name race
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {Array} tasks - An array containing [async functions]{@link AsyncFunction}
+     * to run. Each function can complete with an optional `result` value.
+     * @param {Function} callback - A callback to run once any of the functions have
+     * completed. This function gets an error or result from the first function that
+     * completed. Invoked with (err, result).
+     * @returns {Promise} a promise, if a callback is omitted
+     * @example
+     *
+     * async.race([
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'one');
+     *         }, 200);
+     *     },
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'two');
+     *         }, 100);
+     *     }
+     * ],
+     * // main callback
+     * function(err, result) {
+     *     // the result will be equal to 'two' as it finishes earlier
+     * });
+     */
+    function race(tasks, callback) {
+        callback = once(callback);
+        if (!Array.isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions'));
+        if (!tasks.length) return callback();
+        for (var i = 0, l = tasks.length; i < l; i++) {
+            wrapAsync(tasks[i])(callback);
+        }
+    }
+
+    var race$1 = awaitify(race, 2);
+
+    /**
+     * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order.
+     *
+     * @name reduceRight
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.reduce]{@link module:Collections.reduce}
+     * @alias foldr
+     * @category Collection
+     * @param {Array} array - A collection to iterate over.
+     * @param {*} memo - The initial state of the reduction.
+     * @param {AsyncFunction} iteratee - A function applied to each item in the
+     * array to produce the next step in the reduction.
+     * The `iteratee` should complete with the next state of the reduction.
+     * If the iteratee completes with an error, the reduction is stopped and the
+     * main `callback` is immediately called with the error.
+     * Invoked with (memo, item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Result is the reduced value. Invoked with
+     * (err, result).
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function reduceRight (array, memo, iteratee, callback) {
+        var reversed = [...array].reverse();
+        return reduce$1(reversed, memo, iteratee, callback);
+    }
+
+    /**
+     * Wraps the async function in another function that always completes with a
+     * result object, even when it errors.
+     *
+     * The result object has either the property `error` or `value`.
+     *
+     * @name reflect
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @category Util
+     * @param {AsyncFunction} fn - The async function you want to wrap
+     * @returns {Function} - A function that always passes null to it's callback as
+     * the error. The second argument to the callback will be an `object` with
+     * either an `error` or a `value` property.
+     * @example
+     *
+     * async.parallel([
+     *     async.reflect(function(callback) {
+     *         // do some stuff ...
+     *         callback(null, 'one');
+     *     }),
+     *     async.reflect(function(callback) {
+     *         // do some more stuff but error ...
+     *         callback('bad stuff happened');
+     *     }),
+     *     async.reflect(function(callback) {
+     *         // do some more stuff ...
+     *         callback(null, 'two');
+     *     })
+     * ],
+     * // optional callback
+     * function(err, results) {
+     *     // values
+     *     // results[0].value = 'one'
+     *     // results[1].error = 'bad stuff happened'
+     *     // results[2].value = 'two'
+     * });
+     */
+    function reflect(fn) {
+        var _fn = wrapAsync(fn);
+        return initialParams(function reflectOn(args, reflectCallback) {
+            args.push((error, ...cbArgs) => {
+                let retVal = {};
+                if (error) {
+                    retVal.error = error;
+                }
+                if (cbArgs.length > 0){
+                    var value = cbArgs;
+                    if (cbArgs.length <= 1) {
+                        [value] = cbArgs;
+                    }
+                    retVal.value = value;
+                }
+                reflectCallback(null, retVal);
+            });
+
+            return _fn.apply(this, args);
+        });
+    }
+
+    /**
+     * A helper function that wraps an array or an object of functions with `reflect`.
+     *
+     * @name reflectAll
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @see [async.reflect]{@link module:Utils.reflect}
+     * @category Util
+     * @param {Array|Object|Iterable} tasks - The collection of
+     * [async functions]{@link AsyncFunction} to wrap in `async.reflect`.
+     * @returns {Array} Returns an array of async functions, each wrapped in
+     * `async.reflect`
+     * @example
+     *
+     * let tasks = [
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'one');
+     *         }, 200);
+     *     },
+     *     function(callback) {
+     *         // do some more stuff but error ...
+     *         callback(new Error('bad stuff happened'));
+     *     },
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'two');
+     *         }, 100);
+     *     }
+     * ];
+     *
+     * async.parallel(async.reflectAll(tasks),
+     * // optional callback
+     * function(err, results) {
+     *     // values
+     *     // results[0].value = 'one'
+     *     // results[1].error = Error('bad stuff happened')
+     *     // results[2].value = 'two'
+     * });
+     *
+     * // an example using an object instead of an array
+     * let tasks = {
+     *     one: function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'one');
+     *         }, 200);
+     *     },
+     *     two: function(callback) {
+     *         callback('two');
+     *     },
+     *     three: function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'three');
+     *         }, 100);
+     *     }
+     * };
+     *
+     * async.parallel(async.reflectAll(tasks),
+     * // optional callback
+     * function(err, results) {
+     *     // values
+     *     // results.one.value = 'one'
+     *     // results.two.error = 'two'
+     *     // results.three.value = 'three'
+     * });
+     */
+    function reflectAll(tasks) {
+        var results;
+        if (Array.isArray(tasks)) {
+            results = tasks.map(reflect);
+        } else {
+            results = {};
+            Object.keys(tasks).forEach(key => {
+                results[key] = reflect.call(this, tasks[key]);
+            });
+        }
+        return results;
+    }
+
+    function reject(eachfn, arr, _iteratee, callback) {
+        const iteratee = wrapAsync(_iteratee);
+        return _filter(eachfn, arr, (value, cb) => {
+            iteratee(value, (err, v) => {
+                cb(err, !v);
+            });
+        }, callback);
+    }
+
+    /**
+     * The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test.
+     *
+     * @name reject
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.filter]{@link module:Collections.filter}
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {Function} iteratee - An async truth test to apply to each item in
+     * `coll`.
+     * The should complete with a boolean value as its `result`.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Invoked with (err, results).
+     * @returns {Promise} a promise, if no callback is passed
+     * @example
+     *
+     * // dir1 is a directory that contains file1.txt, file2.txt
+     * // dir2 is a directory that contains file3.txt, file4.txt
+     * // dir3 is a directory that contains file5.txt
+     *
+     * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt'];
+     *
+     * // asynchronous function that checks if a file exists
+     * function fileExists(file, callback) {
+     *    fs.access(file, fs.constants.F_OK, (err) => {
+     *        callback(null, !err);
+     *    });
+     * }
+     *
+     * // Using callbacks
+     * async.reject(fileList, fileExists, function(err, results) {
+     *    // [ 'dir3/file6.txt' ]
+     *    // results now equals an array of the non-existing files
+     * });
+     *
+     * // Using Promises
+     * async.reject(fileList, fileExists)
+     * .then( results => {
+     *     console.log(results);
+     *     // [ 'dir3/file6.txt' ]
+     *     // results now equals an array of the non-existing files
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let results = await async.reject(fileList, fileExists);
+     *         console.log(results);
+     *         // [ 'dir3/file6.txt' ]
+     *         // results now equals an array of the non-existing files
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function reject$1 (coll, iteratee, callback) {
+        return reject(eachOf$1, coll, iteratee, callback)
+    }
+    var reject$2 = awaitify(reject$1, 3);
+
+    /**
+     * The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a
+     * time.
+     *
+     * @name rejectLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.reject]{@link module:Collections.reject}
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {Function} iteratee - An async truth test to apply to each item in
+     * `coll`.
+     * The should complete with a boolean value as its `result`.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Invoked with (err, results).
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function rejectLimit (coll, limit, iteratee, callback) {
+        return reject(eachOfLimit(limit), coll, iteratee, callback)
+    }
+    var rejectLimit$1 = awaitify(rejectLimit, 4);
+
+    /**
+     * The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time.
+     *
+     * @name rejectSeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.reject]{@link module:Collections.reject}
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {Function} iteratee - An async truth test to apply to each item in
+     * `coll`.
+     * The should complete with a boolean value as its `result`.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Invoked with (err, results).
+     * @returns {Promise} a promise, if no callback is passed
+     */
+    function rejectSeries (coll, iteratee, callback) {
+        return reject(eachOfSeries$1, coll, iteratee, callback)
+    }
+    var rejectSeries$1 = awaitify(rejectSeries, 3);
+
+    function constant$1(value) {
+        return function () {
+            return value;
+        }
+    }
+
+    /**
+     * Attempts to get a successful response from `task` no more than `times` times
+     * before returning an error. If the task is successful, the `callback` will be
+     * passed the result of the successful task. If all attempts fail, the callback
+     * will be passed the error and result (if any) of the final attempt.
+     *
+     * @name retry
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @see [async.retryable]{@link module:ControlFlow.retryable}
+     * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an
+     * object with `times` and `interval` or a number.
+     * * `times` - The number of attempts to make before giving up.  The default
+     *   is `5`.
+     * * `interval` - The time to wait between retries, in milliseconds.  The
+     *   default is `0`. The interval may also be specified as a function of the
+     *   retry count (see example).
+     * * `errorFilter` - An optional synchronous function that is invoked on
+     *   erroneous result. If it returns `true` the retry attempts will continue;
+     *   if the function returns `false` the retry flow is aborted with the current
+     *   attempt's error and result being returned to the final callback.
+     *   Invoked with (err).
+     * * If `opts` is a number, the number specifies the number of times to retry,
+     *   with the default interval of `0`.
+     * @param {AsyncFunction} task - An async function to retry.
+     * Invoked with (callback).
+     * @param {Function} [callback] - An optional callback which is called when the
+     * task has succeeded, or after the final failed attempt. It receives the `err`
+     * and `result` arguments of the last attempt at completing the `task`. Invoked
+     * with (err, results).
+     * @returns {Promise} a promise if no callback provided
+     *
+     * @example
+     *
+     * // The `retry` function can be used as a stand-alone control flow by passing
+     * // a callback, as shown below:
+     *
+     * // try calling apiMethod 3 times
+     * async.retry(3, apiMethod, function(err, result) {
+     *     // do something with the result
+     * });
+     *
+     * // try calling apiMethod 3 times, waiting 200 ms between each retry
+     * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
+     *     // do something with the result
+     * });
+     *
+     * // try calling apiMethod 10 times with exponential backoff
+     * // (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds)
+     * async.retry({
+     *   times: 10,
+     *   interval: function(retryCount) {
+     *     return 50 * Math.pow(2, retryCount);
+     *   }
+     * }, apiMethod, function(err, result) {
+     *     // do something with the result
+     * });
+     *
+     * // try calling apiMethod the default 5 times no delay between each retry
+     * async.retry(apiMethod, function(err, result) {
+     *     // do something with the result
+     * });
+     *
+     * // try calling apiMethod only when error condition satisfies, all other
+     * // errors will abort the retry control flow and return to final callback
+     * async.retry({
+     *   errorFilter: function(err) {
+     *     return err.message === 'Temporary error'; // only retry on a specific error
+     *   }
+     * }, apiMethod, function(err, result) {
+     *     // do something with the result
+     * });
+     *
+     * // to retry individual methods that are not as reliable within other
+     * // control flow functions, use the `retryable` wrapper:
+     * async.auto({
+     *     users: api.getUsers.bind(api),
+     *     payments: async.retryable(3, api.getPayments.bind(api))
+     * }, function(err, results) {
+     *     // do something with the results
+     * });
+     *
+     */
+    const DEFAULT_TIMES = 5;
+    const DEFAULT_INTERVAL = 0;
+
+    function retry(opts, task, callback) {
+        var options = {
+            times: DEFAULT_TIMES,
+            intervalFunc: constant$1(DEFAULT_INTERVAL)
+        };
+
+        if (arguments.length < 3 && typeof opts === 'function') {
+            callback = task || promiseCallback();
+            task = opts;
+        } else {
+            parseTimes(options, opts);
+            callback = callback || promiseCallback();
+        }
+
+        if (typeof task !== 'function') {
+            throw new Error("Invalid arguments for async.retry");
+        }
+
+        var _task = wrapAsync(task);
+
+        var attempt = 1;
+        function retryAttempt() {
+            _task((err, ...args) => {
+                if (err === false) return
+                if (err && attempt++ < options.times &&
+                    (typeof options.errorFilter != 'function' ||
+                        options.errorFilter(err))) {
+                    setTimeout(retryAttempt, options.intervalFunc(attempt - 1));
+                } else {
+                    callback(err, ...args);
+                }
+            });
+        }
+
+        retryAttempt();
+        return callback[PROMISE_SYMBOL]
+    }
+
+    function parseTimes(acc, t) {
+        if (typeof t === 'object') {
+            acc.times = +t.times || DEFAULT_TIMES;
+
+            acc.intervalFunc = typeof t.interval === 'function' ?
+                t.interval :
+                constant$1(+t.interval || DEFAULT_INTERVAL);
+
+            acc.errorFilter = t.errorFilter;
+        } else if (typeof t === 'number' || typeof t === 'string') {
+            acc.times = +t || DEFAULT_TIMES;
+        } else {
+            throw new Error("Invalid arguments for async.retry");
+        }
+    }
+
+    /**
+     * A close relative of [`retry`]{@link module:ControlFlow.retry}.  This method
+     * wraps a task and makes it retryable, rather than immediately calling it
+     * with retries.
+     *
+     * @name retryable
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.retry]{@link module:ControlFlow.retry}
+     * @category Control Flow
+     * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional
+     * options, exactly the same as from `retry`, except for a `opts.arity` that
+     * is the arity of the `task` function, defaulting to `task.length`
+     * @param {AsyncFunction} task - the asynchronous function to wrap.
+     * This function will be passed any arguments passed to the returned wrapper.
+     * Invoked with (...args, callback).
+     * @returns {AsyncFunction} The wrapped function, which when invoked, will
+     * retry on an error, based on the parameters specified in `opts`.
+     * This function will accept the same parameters as `task`.
+     * @example
+     *
+     * async.auto({
+     *     dep1: async.retryable(3, getFromFlakyService),
+     *     process: ["dep1", async.retryable(3, function (results, cb) {
+     *         maybeProcessData(results.dep1, cb);
+     *     })]
+     * }, callback);
+     */
+    function retryable (opts, task) {
+        if (!task) {
+            task = opts;
+            opts = null;
+        }
+        let arity = (opts && opts.arity) || task.length;
+        if (isAsync(task)) {
+            arity += 1;
+        }
+        var _task = wrapAsync(task);
+        return initialParams((args, callback) => {
+            if (args.length < arity - 1 || callback == null) {
+                args.push(callback);
+                callback = promiseCallback();
+            }
+            function taskFn(cb) {
+                _task(...args, cb);
+            }
+
+            if (opts) retry(opts, taskFn, callback);
+            else retry(taskFn, callback);
+
+            return callback[PROMISE_SYMBOL]
+        });
+    }
+
+    /**
+     * Run the functions in the `tasks` collection in series, each one running once
+     * the previous function has completed. If any functions in the series pass an
+     * error to its callback, no more functions are run, and `callback` is
+     * immediately called with the value of the error. Otherwise, `callback`
+     * receives an array of results when `tasks` have completed.
+     *
+     * It is also possible to use an object instead of an array. Each property will
+     * be run as a function, and the results will be passed to the final `callback`
+     * as an object instead of an array. This can be a more readable way of handling
+     *  results from {@link async.series}.
+     *
+     * **Note** that while many implementations preserve the order of object
+     * properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6)
+     * explicitly states that
+     *
+     * > The mechanics and order of enumerating the properties is not specified.
+     *
+     * So if you rely on the order in which your series of functions are executed,
+     * and want this to work on all platforms, consider using an array.
+     *
+     * @name series
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing
+     * [async functions]{@link AsyncFunction} to run in series.
+     * Each function can complete with any number of optional `result` values.
+     * @param {Function} [callback] - An optional callback to run once all the
+     * functions have completed. This function gets a results array (or object)
+     * containing all the result arguments passed to the `task` callbacks. Invoked
+     * with (err, result).
+     * @return {Promise} a promise, if no callback is passed
+     * @example
+     *
+     * //Using Callbacks
+     * async.series([
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             // do some async task
+     *             callback(null, 'one');
+     *         }, 200);
+     *     },
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             // then do another async task
+     *             callback(null, 'two');
+     *         }, 100);
+     *     }
+     * ], function(err, results) {
+     *     console.log(results);
+     *     // results is equal to ['one','two']
+     * });
+     *
+     * // an example using objects instead of arrays
+     * async.series({
+     *     one: function(callback) {
+     *         setTimeout(function() {
+     *             // do some async task
+     *             callback(null, 1);
+     *         }, 200);
+     *     },
+     *     two: function(callback) {
+     *         setTimeout(function() {
+     *             // then do another async task
+     *             callback(null, 2);
+     *         }, 100);
+     *     }
+     * }, function(err, results) {
+     *     console.log(results);
+     *     // results is equal to: { one: 1, two: 2 }
+     * });
+     *
+     * //Using Promises
+     * async.series([
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'one');
+     *         }, 200);
+     *     },
+     *     function(callback) {
+     *         setTimeout(function() {
+     *             callback(null, 'two');
+     *         }, 100);
+     *     }
+     * ]).then(results => {
+     *     console.log(results);
+     *     // results is equal to ['one','two']
+     * }).catch(err => {
+     *     console.log(err);
+     * });
+     *
+     * // an example using an object instead of an array
+     * async.series({
+     *     one: function(callback) {
+     *         setTimeout(function() {
+     *             // do some async task
+     *             callback(null, 1);
+     *         }, 200);
+     *     },
+     *     two: function(callback) {
+     *         setTimeout(function() {
+     *             // then do another async task
+     *             callback(null, 2);
+     *         }, 100);
+     *     }
+     * }).then(results => {
+     *     console.log(results);
+     *     // results is equal to: { one: 1, two: 2 }
+     * }).catch(err => {
+     *     console.log(err);
+     * });
+     *
+     * //Using async/await
+     * async () => {
+     *     try {
+     *         let results = await async.series([
+     *             function(callback) {
+     *                 setTimeout(function() {
+     *                     // do some async task
+     *                     callback(null, 'one');
+     *                 }, 200);
+     *             },
+     *             function(callback) {
+     *                 setTimeout(function() {
+     *                     // then do another async task
+     *                     callback(null, 'two');
+     *                 }, 100);
+     *             }
+     *         ]);
+     *         console.log(results);
+     *         // results is equal to ['one','two']
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * // an example using an object instead of an array
+     * async () => {
+     *     try {
+     *         let results = await async.parallel({
+     *             one: function(callback) {
+     *                 setTimeout(function() {
+     *                     // do some async task
+     *                     callback(null, 1);
+     *                 }, 200);
+     *             },
+     *            two: function(callback) {
+     *                 setTimeout(function() {
+     *                     // then do another async task
+     *                     callback(null, 2);
+     *                 }, 100);
+     *            }
+     *         });
+     *         console.log(results);
+     *         // results is equal to: { one: 1, two: 2 }
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function series(tasks, callback) {
+        return parallel(eachOfSeries$1, tasks, callback);
+    }
+
+    /**
+     * Returns `true` if at least one element in the `coll` satisfies an async test.
+     * If any iteratee call returns `true`, the main `callback` is immediately
+     * called.
+     *
+     * @name some
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @alias any
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+     * in the collections in parallel.
+     * The iteratee should complete with a boolean `result` value.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called as soon as any
+     * iteratee returns `true`, or after all the iteratee functions have finished.
+     * Result will be either `true` or `false` depending on the values of the async
+     * tests. Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback provided
+     * @example
+     *
+     * // dir1 is a directory that contains file1.txt, file2.txt
+     * // dir2 is a directory that contains file3.txt, file4.txt
+     * // dir3 is a directory that contains file5.txt
+     * // dir4 does not exist
+     *
+     * // asynchronous function that checks if a file exists
+     * function fileExists(file, callback) {
+     *    fs.access(file, fs.constants.F_OK, (err) => {
+     *        callback(null, !err);
+     *    });
+     * }
+     *
+     * // Using callbacks
+     * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists,
+     *    function(err, result) {
+     *        console.log(result);
+     *        // true
+     *        // result is true since some file in the list exists
+     *    }
+     *);
+     *
+     * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists,
+     *    function(err, result) {
+     *        console.log(result);
+     *        // false
+     *        // result is false since none of the files exists
+     *    }
+     *);
+     *
+     * // Using Promises
+     * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists)
+     * .then( result => {
+     *     console.log(result);
+     *     // true
+     *     // result is true since some file in the list exists
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists)
+     * .then( result => {
+     *     console.log(result);
+     *     // false
+     *     // result is false since none of the files exists
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists);
+     *         console.log(result);
+     *         // true
+     *         // result is true since some file in the list exists
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     * async () => {
+     *     try {
+     *         let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists);
+     *         console.log(result);
+     *         // false
+     *         // result is false since none of the files exists
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function some(coll, iteratee, callback) {
+        return _createTester(Boolean, res => res)(eachOf$1, coll, iteratee, callback)
+    }
+    var some$1 = awaitify(some, 3);
+
+    /**
+     * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time.
+     *
+     * @name someLimit
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.some]{@link module:Collections.some}
+     * @alias anyLimit
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+     * in the collections in parallel.
+     * The iteratee should complete with a boolean `result` value.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called as soon as any
+     * iteratee returns `true`, or after all the iteratee functions have finished.
+     * Result will be either `true` or `false` depending on the values of the async
+     * tests. Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback provided
+     */
+    function someLimit(coll, limit, iteratee, callback) {
+        return _createTester(Boolean, res => res)(eachOfLimit(limit), coll, iteratee, callback)
+    }
+    var someLimit$1 = awaitify(someLimit, 4);
+
+    /**
+     * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time.
+     *
+     * @name someSeries
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @see [async.some]{@link module:Collections.some}
+     * @alias anySeries
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+     * in the collections in series.
+     * The iteratee should complete with a boolean `result` value.
+     * Invoked with (item, callback).
+     * @param {Function} [callback] - A callback which is called as soon as any
+     * iteratee returns `true`, or after all the iteratee functions have finished.
+     * Result will be either `true` or `false` depending on the values of the async
+     * tests. Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback provided
+     */
+    function someSeries(coll, iteratee, callback) {
+        return _createTester(Boolean, res => res)(eachOfSeries$1, coll, iteratee, callback)
+    }
+    var someSeries$1 = awaitify(someSeries, 3);
+
+    /**
+     * Sorts a list by the results of running each `coll` value through an async
+     * `iteratee`.
+     *
+     * @name sortBy
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {AsyncFunction} iteratee - An async function to apply to each item in
+     * `coll`.
+     * The iteratee should complete with a value to use as the sort criteria as
+     * its `result`.
+     * Invoked with (item, callback).
+     * @param {Function} callback - A callback which is called after all the
+     * `iteratee` functions have finished, or an error occurs. Results is the items
+     * from the original `coll` sorted by the values returned by the `iteratee`
+     * calls. Invoked with (err, results).
+     * @returns {Promise} a promise, if no callback passed
+     * @example
+     *
+     * // bigfile.txt is a file that is 251100 bytes in size
+     * // mediumfile.txt is a file that is 11000 bytes in size
+     * // smallfile.txt is a file that is 121 bytes in size
+     *
+     * // asynchronous function that returns the file size in bytes
+     * function getFileSizeInBytes(file, callback) {
+     *     fs.stat(file, function(err, stat) {
+     *         if (err) {
+     *             return callback(err);
+     *         }
+     *         callback(null, stat.size);
+     *     });
+     * }
+     *
+     * // Using callbacks
+     * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes,
+     *     function(err, results) {
+     *         if (err) {
+     *             console.log(err);
+     *         } else {
+     *             console.log(results);
+     *             // results is now the original array of files sorted by
+     *             // file size (ascending by default), e.g.
+     *             // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+     *         }
+     *     }
+     * );
+     *
+     * // By modifying the callback parameter the
+     * // sorting order can be influenced:
+     *
+     * // ascending order
+     * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], function(file, callback) {
+     *     getFileSizeInBytes(file, function(getFileSizeErr, fileSize) {
+     *         if (getFileSizeErr) return callback(getFileSizeErr);
+     *         callback(null, fileSize);
+     *     });
+     * }, function(err, results) {
+     *         if (err) {
+     *             console.log(err);
+     *         } else {
+     *             console.log(results);
+     *             // results is now the original array of files sorted by
+     *             // file size (ascending by default), e.g.
+     *             // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+     *         }
+     *     }
+     * );
+     *
+     * // descending order
+     * async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], function(file, callback) {
+     *     getFileSizeInBytes(file, function(getFileSizeErr, fileSize) {
+     *         if (getFileSizeErr) {
+     *             return callback(getFileSizeErr);
+     *         }
+     *         callback(null, fileSize * -1);
+     *     });
+     * }, function(err, results) {
+     *         if (err) {
+     *             console.log(err);
+     *         } else {
+     *             console.log(results);
+     *             // results is now the original array of files sorted by
+     *             // file size (ascending by default), e.g.
+     *             // [ 'bigfile.txt', 'mediumfile.txt', 'smallfile.txt']
+     *         }
+     *     }
+     * );
+     *
+     * // Error handling
+     * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes,
+     *     function(err, results) {
+     *         if (err) {
+     *             console.log(err);
+     *             // [ Error: ENOENT: no such file or directory ]
+     *         } else {
+     *             console.log(results);
+     *         }
+     *     }
+     * );
+     *
+     * // Using Promises
+     * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes)
+     * .then( results => {
+     *     console.log(results);
+     *     // results is now the original array of files sorted by
+     *     // file size (ascending by default), e.g.
+     *     // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+     * }).catch( err => {
+     *     console.log(err);
+     * });
+     *
+     * // Error handling
+     * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes)
+     * .then( results => {
+     *     console.log(results);
+     * }).catch( err => {
+     *     console.log(err);
+     *     // [ Error: ENOENT: no such file or directory ]
+     * });
+     *
+     * // Using async/await
+     * (async () => {
+     *     try {
+     *         let results = await async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes);
+     *         console.log(results);
+     *         // results is now the original array of files sorted by
+     *         // file size (ascending by default), e.g.
+     *         // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * })();
+     *
+     * // Error handling
+     * async () => {
+     *     try {
+     *         let results = await async.sortBy(['missingfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes);
+     *         console.log(results);
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *         // [ Error: ENOENT: no such file or directory ]
+     *     }
+     * }
+     *
+     */
+    function sortBy (coll, iteratee, callback) {
+        var _iteratee = wrapAsync(iteratee);
+        return map$1(coll, (x, iterCb) => {
+            _iteratee(x, (err, criteria) => {
+                if (err) return iterCb(err);
+                iterCb(err, {value: x, criteria});
+            });
+        }, (err, results) => {
+            if (err) return callback(err);
+            callback(null, results.sort(comparator).map(v => v.value));
+        });
+
+        function comparator(left, right) {
+            var a = left.criteria, b = right.criteria;
+            return a < b ? -1 : a > b ? 1 : 0;
+        }
+    }
+    var sortBy$1 = awaitify(sortBy, 3);
+
+    /**
+     * Sets a time limit on an asynchronous function. If the function does not call
+     * its callback within the specified milliseconds, it will be called with a
+     * timeout error. The code property for the error object will be `'ETIMEDOUT'`.
+     *
+     * @name timeout
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @category Util
+     * @param {AsyncFunction} asyncFn - The async function to limit in time.
+     * @param {number} milliseconds - The specified time limit.
+     * @param {*} [info] - Any variable you want attached (`string`, `object`, etc)
+     * to timeout Error for more information..
+     * @returns {AsyncFunction} Returns a wrapped function that can be used with any
+     * of the control flow functions.
+     * Invoke this function with the same parameters as you would `asyncFunc`.
+     * @example
+     *
+     * function myFunction(foo, callback) {
+     *     doAsyncTask(foo, function(err, data) {
+     *         // handle errors
+     *         if (err) return callback(err);
+     *
+     *         // do some stuff ...
+     *
+     *         // return processed data
+     *         return callback(null, data);
+     *     });
+     * }
+     *
+     * var wrapped = async.timeout(myFunction, 1000);
+     *
+     * // call `wrapped` as you would `myFunction`
+     * wrapped({ bar: 'bar' }, function(err, data) {
+     *     // if `myFunction` takes < 1000 ms to execute, `err`
+     *     // and `data` will have their expected values
+     *
+     *     // else `err` will be an Error with the code 'ETIMEDOUT'
+     * });
+     */
+    function timeout(asyncFn, milliseconds, info) {
+        var fn = wrapAsync(asyncFn);
+
+        return initialParams((args, callback) => {
+            var timedOut = false;
+            var timer;
+
+            function timeoutCallback() {
+                var name = asyncFn.name || 'anonymous';
+                var error  = new Error('Callback function "' + name + '" timed out.');
+                error.code = 'ETIMEDOUT';
+                if (info) {
+                    error.info = info;
+                }
+                timedOut = true;
+                callback(error);
+            }
+
+            args.push((...cbArgs) => {
+                if (!timedOut) {
+                    callback(...cbArgs);
+                    clearTimeout(timer);
+                }
+            });
+
+            // setup timer and call original function
+            timer = setTimeout(timeoutCallback, milliseconds);
+            fn(...args);
+        });
+    }
+
+    function range(size) {
+        var result = Array(size);
+        while (size--) {
+            result[size] = size;
+        }
+        return result;
+    }
+
+    /**
+     * The same as [times]{@link module:ControlFlow.times} but runs a maximum of `limit` async operations at a
+     * time.
+     *
+     * @name timesLimit
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.times]{@link module:ControlFlow.times}
+     * @category Control Flow
+     * @param {number} count - The number of times to run the function.
+     * @param {number} limit - The maximum number of async operations at a time.
+     * @param {AsyncFunction} iteratee - The async function to call `n` times.
+     * Invoked with the iteration index and a callback: (n, next).
+     * @param {Function} callback - see [async.map]{@link module:Collections.map}.
+     * @returns {Promise} a promise, if no callback is provided
+     */
+    function timesLimit(count, limit, iteratee, callback) {
+        var _iteratee = wrapAsync(iteratee);
+        return mapLimit$1(range(count), limit, _iteratee, callback);
+    }
+
+    /**
+     * Calls the `iteratee` function `n` times, and accumulates results in the same
+     * manner you would use with [map]{@link module:Collections.map}.
+     *
+     * @name times
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.map]{@link module:Collections.map}
+     * @category Control Flow
+     * @param {number} n - The number of times to run the function.
+     * @param {AsyncFunction} iteratee - The async function to call `n` times.
+     * Invoked with the iteration index and a callback: (n, next).
+     * @param {Function} callback - see {@link module:Collections.map}.
+     * @returns {Promise} a promise, if no callback is provided
+     * @example
+     *
+     * // Pretend this is some complicated async factory
+     * var createUser = function(id, callback) {
+     *     callback(null, {
+     *         id: 'user' + id
+     *     });
+     * };
+     *
+     * // generate 5 users
+     * async.times(5, function(n, next) {
+     *     createUser(n, function(err, user) {
+     *         next(err, user);
+     *     });
+     * }, function(err, users) {
+     *     // we should now have 5 users
+     * });
+     */
+    function times (n, iteratee, callback) {
+        return timesLimit(n, Infinity, iteratee, callback)
+    }
+
+    /**
+     * The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time.
+     *
+     * @name timesSeries
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.times]{@link module:ControlFlow.times}
+     * @category Control Flow
+     * @param {number} n - The number of times to run the function.
+     * @param {AsyncFunction} iteratee - The async function to call `n` times.
+     * Invoked with the iteration index and a callback: (n, next).
+     * @param {Function} callback - see {@link module:Collections.map}.
+     * @returns {Promise} a promise, if no callback is provided
+     */
+    function timesSeries (n, iteratee, callback) {
+        return timesLimit(n, 1, iteratee, callback)
+    }
+
+    /**
+     * A relative of `reduce`.  Takes an Object or Array, and iterates over each
+     * element in parallel, each step potentially mutating an `accumulator` value.
+     * The type of the accumulator defaults to the type of collection passed in.
+     *
+     * @name transform
+     * @static
+     * @memberOf module:Collections
+     * @method
+     * @category Collection
+     * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+     * @param {*} [accumulator] - The initial state of the transform.  If omitted,
+     * it will default to an empty Object or Array, depending on the type of `coll`
+     * @param {AsyncFunction} iteratee - A function applied to each item in the
+     * collection that potentially modifies the accumulator.
+     * Invoked with (accumulator, item, key, callback).
+     * @param {Function} [callback] - A callback which is called after all the
+     * `iteratee` functions have finished. Result is the transformed accumulator.
+     * Invoked with (err, result).
+     * @returns {Promise} a promise, if no callback provided
+     * @example
+     *
+     * // file1.txt is a file that is 1000 bytes in size
+     * // file2.txt is a file that is 2000 bytes in size
+     * // file3.txt is a file that is 3000 bytes in size
+     *
+     * // helper function that returns human-readable size format from bytes
+     * function formatBytes(bytes, decimals = 2) {
+     *   // implementation not included for brevity
+     *   return humanReadbleFilesize;
+     * }
+     *
+     * const fileList = ['file1.txt','file2.txt','file3.txt'];
+     *
+     * // asynchronous function that returns the file size, transformed to human-readable format
+     * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc.
+     * function transformFileSize(acc, value, key, callback) {
+     *     fs.stat(value, function(err, stat) {
+     *         if (err) {
+     *             return callback(err);
+     *         }
+     *         acc[key] = formatBytes(stat.size);
+     *         callback(null);
+     *     });
+     * }
+     *
+     * // Using callbacks
+     * async.transform(fileList, transformFileSize, function(err, result) {
+     *     if(err) {
+     *         console.log(err);
+     *     } else {
+     *         console.log(result);
+     *         // [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
+     *     }
+     * });
+     *
+     * // Using Promises
+     * async.transform(fileList, transformFileSize)
+     * .then(result => {
+     *     console.log(result);
+     *     // [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
+     * }).catch(err => {
+     *     console.log(err);
+     * });
+     *
+     * // Using async/await
+     * (async () => {
+     *     try {
+     *         let result = await async.transform(fileList, transformFileSize);
+     *         console.log(result);
+     *         // [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * })();
+     *
+     * @example
+     *
+     * // file1.txt is a file that is 1000 bytes in size
+     * // file2.txt is a file that is 2000 bytes in size
+     * // file3.txt is a file that is 3000 bytes in size
+     *
+     * // helper function that returns human-readable size format from bytes
+     * function formatBytes(bytes, decimals = 2) {
+     *   // implementation not included for brevity
+     *   return humanReadbleFilesize;
+     * }
+     *
+     * const fileMap = { f1: 'file1.txt', f2: 'file2.txt', f3: 'file3.txt' };
+     *
+     * // asynchronous function that returns the file size, transformed to human-readable format
+     * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc.
+     * function transformFileSize(acc, value, key, callback) {
+     *     fs.stat(value, function(err, stat) {
+     *         if (err) {
+     *             return callback(err);
+     *         }
+     *         acc[key] = formatBytes(stat.size);
+     *         callback(null);
+     *     });
+     * }
+     *
+     * // Using callbacks
+     * async.transform(fileMap, transformFileSize, function(err, result) {
+     *     if(err) {
+     *         console.log(err);
+     *     } else {
+     *         console.log(result);
+     *         // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
+     *     }
+     * });
+     *
+     * // Using Promises
+     * async.transform(fileMap, transformFileSize)
+     * .then(result => {
+     *     console.log(result);
+     *     // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
+     * }).catch(err => {
+     *     console.log(err);
+     * });
+     *
+     * // Using async/await
+     * async () => {
+     *     try {
+     *         let result = await async.transform(fileMap, transformFileSize);
+     *         console.log(result);
+     *         // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
+     *     }
+     *     catch (err) {
+     *         console.log(err);
+     *     }
+     * }
+     *
+     */
+    function transform (coll, accumulator, iteratee, callback) {
+        if (arguments.length <= 3 && typeof accumulator === 'function') {
+            callback = iteratee;
+            iteratee = accumulator;
+            accumulator = Array.isArray(coll) ? [] : {};
+        }
+        callback = once(callback || promiseCallback());
+        var _iteratee = wrapAsync(iteratee);
+
+        eachOf$1(coll, (v, k, cb) => {
+            _iteratee(accumulator, v, k, cb);
+        }, err => callback(err, accumulator));
+        return callback[PROMISE_SYMBOL]
+    }
+
+    /**
+     * It runs each task in series but stops whenever any of the functions were
+     * successful. If one of the tasks were successful, the `callback` will be
+     * passed the result of the successful task. If all tasks fail, the callback
+     * will be passed the error and result (if any) of the final attempt.
+     *
+     * @name tryEach
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing functions to
+     * run, each function is passed a `callback(err, result)` it must call on
+     * completion with an error `err` (which can be `null`) and an optional `result`
+     * value.
+     * @param {Function} [callback] - An optional callback which is called when one
+     * of the tasks has succeeded, or all have failed. It receives the `err` and
+     * `result` arguments of the last attempt at completing the `task`. Invoked with
+     * (err, results).
+     * @returns {Promise} a promise, if no callback is passed
+     * @example
+     * async.tryEach([
+     *     function getDataFromFirstWebsite(callback) {
+     *         // Try getting the data from the first website
+     *         callback(err, data);
+     *     },
+     *     function getDataFromSecondWebsite(callback) {
+     *         // First website failed,
+     *         // Try getting the data from the backup website
+     *         callback(err, data);
+     *     }
+     * ],
+     * // optional callback
+     * function(err, results) {
+     *     Now do something with the data.
+     * });
+     *
+     */
+    function tryEach(tasks, callback) {
+        var error = null;
+        var result;
+        return eachSeries$1(tasks, (task, taskCb) => {
+            wrapAsync(task)((err, ...args) => {
+                if (err === false) return taskCb(err);
+
+                if (args.length < 2) {
+                    [result] = args;
+                } else {
+                    result = args;
+                }
+                error = err;
+                taskCb(err ? null : {});
+            });
+        }, () => callback(error, result));
+    }
+
+    var tryEach$1 = awaitify(tryEach);
+
+    /**
+     * Undoes a [memoize]{@link module:Utils.memoize}d function, reverting it to the original,
+     * unmemoized form. Handy for testing.
+     *
+     * @name unmemoize
+     * @static
+     * @memberOf module:Utils
+     * @method
+     * @see [async.memoize]{@link module:Utils.memoize}
+     * @category Util
+     * @param {AsyncFunction} fn - the memoized function
+     * @returns {AsyncFunction} a function that calls the original unmemoized function
+     */
+    function unmemoize(fn) {
+        return (...args) => {
+            return (fn.unmemoized || fn)(...args);
+        };
+    }
+
+    /**
+     * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when
+     * stopped, or an error occurs.
+     *
+     * @name whilst
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {AsyncFunction} test - asynchronous truth test to perform before each
+     * execution of `iteratee`. Invoked with ().
+     * @param {AsyncFunction} iteratee - An async function which is called each time
+     * `test` passes. Invoked with (callback).
+     * @param {Function} [callback] - A callback which is called after the test
+     * function has failed and repeated execution of `iteratee` has stopped. `callback`
+     * will be passed an error and any arguments passed to the final `iteratee`'s
+     * callback. Invoked with (err, [results]);
+     * @returns {Promise} a promise, if no callback is passed
+     * @example
+     *
+     * var count = 0;
+     * async.whilst(
+     *     function test(cb) { cb(null, count < 5); },
+     *     function iter(callback) {
+     *         count++;
+     *         setTimeout(function() {
+     *             callback(null, count);
+     *         }, 1000);
+     *     },
+     *     function (err, n) {
+     *         // 5 seconds have passed, n = 5
+     *     }
+     * );
+     */
+    function whilst(test, iteratee, callback) {
+        callback = onlyOnce(callback);
+        var _fn = wrapAsync(iteratee);
+        var _test = wrapAsync(test);
+        var results = [];
+
+        function next(err, ...rest) {
+            if (err) return callback(err);
+            results = rest;
+            if (err === false) return;
+            _test(check);
+        }
+
+        function check(err, truth) {
+            if (err) return callback(err);
+            if (err === false) return;
+            if (!truth) return callback(null, ...results);
+            _fn(next);
+        }
+
+        return _test(check);
+    }
+    var whilst$1 = awaitify(whilst, 3);
+
+    /**
+     * Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when
+     * stopped, or an error occurs. `callback` will be passed an error and any
+     * arguments passed to the final `iteratee`'s callback.
+     *
+     * The inverse of [whilst]{@link module:ControlFlow.whilst}.
+     *
+     * @name until
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @see [async.whilst]{@link module:ControlFlow.whilst}
+     * @category Control Flow
+     * @param {AsyncFunction} test - asynchronous truth test to perform before each
+     * execution of `iteratee`. Invoked with (callback).
+     * @param {AsyncFunction} iteratee - An async function which is called each time
+     * `test` fails. Invoked with (callback).
+     * @param {Function} [callback] - A callback which is called after the test
+     * function has passed and repeated execution of `iteratee` has stopped. `callback`
+     * will be passed an error and any arguments passed to the final `iteratee`'s
+     * callback. Invoked with (err, [results]);
+     * @returns {Promise} a promise, if a callback is not passed
+     *
+     * @example
+     * const results = []
+     * let finished = false
+     * async.until(function test(cb) {
+     *     cb(null, finished)
+     * }, function iter(next) {
+     *     fetchPage(url, (err, body) => {
+     *         if (err) return next(err)
+     *         results = results.concat(body.objects)
+     *         finished = !!body.next
+     *         next(err)
+     *     })
+     * }, function done (err) {
+     *     // all pages have been fetched
+     * })
+     */
+    function until(test, iteratee, callback) {
+        const _test = wrapAsync(test);
+        return whilst$1((cb) => _test((err, truth) => cb (err, !truth)), iteratee, callback);
+    }
+
+    /**
+     * Runs the `tasks` array of functions in series, each passing their results to
+     * the next in the array. However, if any of the `tasks` pass an error to their
+     * own callback, the next function is not executed, and the main `callback` is
+     * immediately called with the error.
+     *
+     * @name waterfall
+     * @static
+     * @memberOf module:ControlFlow
+     * @method
+     * @category Control Flow
+     * @param {Array} tasks - An array of [async functions]{@link AsyncFunction}
+     * to run.
+     * Each function should complete with any number of `result` values.
+     * The `result` values will be passed as arguments, in order, to the next task.
+     * @param {Function} [callback] - An optional callback to run once all the
+     * functions have completed. This will be passed the results of the last task's
+     * callback. Invoked with (err, [results]).
+     * @returns {Promise} a promise, if a callback is omitted
+     * @example
+     *
+     * async.waterfall([
+     *     function(callback) {
+     *         callback(null, 'one', 'two');
+     *     },
+     *     function(arg1, arg2, callback) {
+     *         // arg1 now equals 'one' and arg2 now equals 'two'
+     *         callback(null, 'three');
+     *     },
+     *     function(arg1, callback) {
+     *         // arg1 now equals 'three'
+     *         callback(null, 'done');
+     *     }
+     * ], function (err, result) {
+     *     // result now equals 'done'
+     * });
+     *
+     * // Or, with named functions:
+     * async.waterfall([
+     *     myFirstFunction,
+     *     mySecondFunction,
+     *     myLastFunction,
+     * ], function (err, result) {
+     *     // result now equals 'done'
+     * });
+     * function myFirstFunction(callback) {
+     *     callback(null, 'one', 'two');
+     * }
+     * function mySecondFunction(arg1, arg2, callback) {
+     *     // arg1 now equals 'one' and arg2 now equals 'two'
+     *     callback(null, 'three');
+     * }
+     * function myLastFunction(arg1, callback) {
+     *     // arg1 now equals 'three'
+     *     callback(null, 'done');
+     * }
+     */
+    function waterfall (tasks, callback) {
+        callback = once(callback);
+        if (!Array.isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions'));
+        if (!tasks.length) return callback();
+        var taskIndex = 0;
+
+        function nextTask(args) {
+            var task = wrapAsync(tasks[taskIndex++]);
+            task(...args, onlyOnce(next));
+        }
+
+        function next(err, ...args) {
+            if (err === false) return
+            if (err || taskIndex === tasks.length) {
+                return callback(err, ...args);
+            }
+            nextTask(args);
+        }
+
+        nextTask([]);
+    }
+
+    var waterfall$1 = awaitify(waterfall);
+
+    /**
+     * An "async function" in the context of Async is an asynchronous function with
+     * a variable number of parameters, with the final parameter being a callback.
+     * (`function (arg1, arg2, ..., callback) {}`)
+     * The final callback is of the form `callback(err, results...)`, which must be
+     * called once the function is completed.  The callback should be called with a
+     * Error as its first argument to signal that an error occurred.
+     * Otherwise, if no error occurred, it should be called with `null` as the first
+     * argument, and any additional `result` arguments that may apply, to signal
+     * successful completion.
+     * The callback must be called exactly once, ideally on a later tick of the
+     * JavaScript event loop.
+     *
+     * This type of function is also referred to as a "Node-style async function",
+     * or a "continuation passing-style function" (CPS). Most of the methods of this
+     * library are themselves CPS/Node-style async functions, or functions that
+     * return CPS/Node-style async functions.
+     *
+     * Wherever we accept a Node-style async function, we also directly accept an
+     * [ES2017 `async` function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function}.
+     * In this case, the `async` function will not be passed a final callback
+     * argument, and any thrown error will be used as the `err` argument of the
+     * implicit callback, and the return value will be used as the `result` value.
+     * (i.e. a `rejected` of the returned Promise becomes the `err` callback
+     * argument, and a `resolved` value becomes the `result`.)
+     *
+     * Note, due to JavaScript limitations, we can only detect native `async`
+     * functions and not transpilied implementations.
+     * Your environment must have `async`/`await` support for this to work.
+     * (e.g. Node > v7.6, or a recent version of a modern browser).
+     * If you are using `async` functions through a transpiler (e.g. Babel), you
+     * must still wrap the function with [asyncify]{@link module:Utils.asyncify},
+     * because the `async function` will be compiled to an ordinary function that
+     * returns a promise.
+     *
+     * @typedef {Function} AsyncFunction
+     * @static
+     */
+
+    var index = {
+        apply,
+        applyEach: applyEach$1,
+        applyEachSeries,
+        asyncify,
+        auto,
+        autoInject,
+        cargo,
+        cargoQueue: cargo$1,
+        compose,
+        concat: concat$1,
+        concatLimit: concatLimit$1,
+        concatSeries: concatSeries$1,
+        constant,
+        detect: detect$1,
+        detectLimit: detectLimit$1,
+        detectSeries: detectSeries$1,
+        dir,
+        doUntil,
+        doWhilst: doWhilst$1,
+        each,
+        eachLimit: eachLimit$2,
+        eachOf: eachOf$1,
+        eachOfLimit: eachOfLimit$2,
+        eachOfSeries: eachOfSeries$1,
+        eachSeries: eachSeries$1,
+        ensureAsync,
+        every: every$1,
+        everyLimit: everyLimit$1,
+        everySeries: everySeries$1,
+        filter: filter$1,
+        filterLimit: filterLimit$1,
+        filterSeries: filterSeries$1,
+        forever: forever$1,
+        groupBy,
+        groupByLimit: groupByLimit$1,
+        groupBySeries,
+        log,
+        map: map$1,
+        mapLimit: mapLimit$1,
+        mapSeries: mapSeries$1,
+        mapValues,
+        mapValuesLimit: mapValuesLimit$1,
+        mapValuesSeries,
+        memoize,
+        nextTick,
+        parallel: parallel$1,
+        parallelLimit,
+        priorityQueue,
+        queue: queue$1,
+        race: race$1,
+        reduce: reduce$1,
+        reduceRight,
+        reflect,
+        reflectAll,
+        reject: reject$2,
+        rejectLimit: rejectLimit$1,
+        rejectSeries: rejectSeries$1,
+        retry,
+        retryable,
+        seq,
+        series,
+        setImmediate: setImmediate$1,
+        some: some$1,
+        someLimit: someLimit$1,
+        someSeries: someSeries$1,
+        sortBy: sortBy$1,
+        timeout,
+        times,
+        timesLimit,
+        timesSeries,
+        transform,
+        tryEach: tryEach$1,
+        unmemoize,
+        until,
+        waterfall: waterfall$1,
+        whilst: whilst$1,
+
+        // aliases
+        all: every$1,
+        allLimit: everyLimit$1,
+        allSeries: everySeries$1,
+        any: some$1,
+        anyLimit: someLimit$1,
+        anySeries: someSeries$1,
+        find: detect$1,
+        findLimit: detectLimit$1,
+        findSeries: detectSeries$1,
+        flatMap: concat$1,
+        flatMapLimit: concatLimit$1,
+        flatMapSeries: concatSeries$1,
+        forEach: each,
+        forEachSeries: eachSeries$1,
+        forEachLimit: eachLimit$2,
+        forEachOf: eachOf$1,
+        forEachOfSeries: eachOfSeries$1,
+        forEachOfLimit: eachOfLimit$2,
+        inject: reduce$1,
+        foldl: reduce$1,
+        foldr: reduceRight,
+        select: filter$1,
+        selectLimit: filterLimit$1,
+        selectSeries: filterSeries$1,
+        wrapSync: asyncify,
+        during: whilst$1,
+        doDuring: doWhilst$1
+    };
+
+    exports.default = index;
+    exports.apply = apply;
+    exports.applyEach = applyEach$1;
+    exports.applyEachSeries = applyEachSeries;
+    exports.asyncify = asyncify;
+    exports.auto = auto;
+    exports.autoInject = autoInject;
+    exports.cargo = cargo;
+    exports.cargoQueue = cargo$1;
+    exports.compose = compose;
+    exports.concat = concat$1;
+    exports.concatLimit = concatLimit$1;
+    exports.concatSeries = concatSeries$1;
+    exports.constant = constant;
+    exports.detect = detect$1;
+    exports.detectLimit = detectLimit$1;
+    exports.detectSeries = detectSeries$1;
+    exports.dir = dir;
+    exports.doUntil = doUntil;
+    exports.doWhilst = doWhilst$1;
+    exports.each = each;
+    exports.eachLimit = eachLimit$2;
+    exports.eachOf = eachOf$1;
+    exports.eachOfLimit = eachOfLimit$2;
+    exports.eachOfSeries = eachOfSeries$1;
+    exports.eachSeries = eachSeries$1;
+    exports.ensureAsync = ensureAsync;
+    exports.every = every$1;
+    exports.everyLimit = everyLimit$1;
+    exports.everySeries = everySeries$1;
+    exports.filter = filter$1;
+    exports.filterLimit = filterLimit$1;
+    exports.filterSeries = filterSeries$1;
+    exports.forever = forever$1;
+    exports.groupBy = groupBy;
+    exports.groupByLimit = groupByLimit$1;
+    exports.groupBySeries = groupBySeries;
+    exports.log = log;
+    exports.map = map$1;
+    exports.mapLimit = mapLimit$1;
+    exports.mapSeries = mapSeries$1;
+    exports.mapValues = mapValues;
+    exports.mapValuesLimit = mapValuesLimit$1;
+    exports.mapValuesSeries = mapValuesSeries;
+    exports.memoize = memoize;
+    exports.nextTick = nextTick;
+    exports.parallel = parallel$1;
+    exports.parallelLimit = parallelLimit;
+    exports.priorityQueue = priorityQueue;
+    exports.queue = queue$1;
+    exports.race = race$1;
+    exports.reduce = reduce$1;
+    exports.reduceRight = reduceRight;
+    exports.reflect = reflect;
+    exports.reflectAll = reflectAll;
+    exports.reject = reject$2;
+    exports.rejectLimit = rejectLimit$1;
+    exports.rejectSeries = rejectSeries$1;
+    exports.retry = retry;
+    exports.retryable = retryable;
+    exports.seq = seq;
+    exports.series = series;
+    exports.setImmediate = setImmediate$1;
+    exports.some = some$1;
+    exports.someLimit = someLimit$1;
+    exports.someSeries = someSeries$1;
+    exports.sortBy = sortBy$1;
+    exports.timeout = timeout;
+    exports.times = times;
+    exports.timesLimit = timesLimit;
+    exports.timesSeries = timesSeries;
+    exports.transform = transform;
+    exports.tryEach = tryEach$1;
+    exports.unmemoize = unmemoize;
+    exports.until = until;
+    exports.waterfall = waterfall$1;
+    exports.whilst = whilst$1;
+    exports.all = every$1;
+    exports.allLimit = everyLimit$1;
+    exports.allSeries = everySeries$1;
+    exports.any = some$1;
+    exports.anyLimit = someLimit$1;
+    exports.anySeries = someSeries$1;
+    exports.find = detect$1;
+    exports.findLimit = detectLimit$1;
+    exports.findSeries = detectSeries$1;
+    exports.flatMap = concat$1;
+    exports.flatMapLimit = concatLimit$1;
+    exports.flatMapSeries = concatSeries$1;
+    exports.forEach = each;
+    exports.forEachSeries = eachSeries$1;
+    exports.forEachLimit = eachLimit$2;
+    exports.forEachOf = eachOf$1;
+    exports.forEachOfSeries = eachOfSeries$1;
+    exports.forEachOfLimit = eachOfLimit$2;
+    exports.inject = reduce$1;
+    exports.foldl = reduce$1;
+    exports.foldr = reduceRight;
+    exports.select = filter$1;
+    exports.selectLimit = filterLimit$1;
+    exports.selectSeries = filterSeries$1;
+    exports.wrapSync = asyncify;
+    exports.during = whilst$1;
+    exports.doDuring = doWhilst$1;
+
+    Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
diff --git a/node_modules/async/dist/async.min.js b/node_modules/async/dist/async.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..a12963b6c25708946f6493e1e6c0eb7e0165a336
--- /dev/null
+++ b/node_modules/async/dist/async.min.js
@@ -0,0 +1 @@
+(function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.async={})})(this,function(e){'use strict';function t(e,...t){return(...n)=>e(...t,...n)}function n(e){return function(...t){var n=t.pop();return e.call(this,t,n)}}function a(e){setTimeout(e,0)}function i(e){return(t,...n)=>e(()=>t(...n))}function r(e){return u(e)?function(...t){const n=t.pop(),a=e.apply(this,t);return s(a,n)}:n(function(t,n){var a;try{a=e.apply(this,t)}catch(t){return n(t)}return a&&"function"==typeof a.then?s(a,n):void n(null,a)})}function s(e,t){return e.then(e=>{l(t,null,e)},e=>{l(t,e&&e.message?e:new Error(e))})}function l(e,t,n){try{e(t,n)}catch(e){_e(t=>{throw t},e)}}function u(e){return"AsyncFunction"===e[Symbol.toStringTag]}function d(e){return"AsyncGenerator"===e[Symbol.toStringTag]}function p(e){return"function"==typeof e[Symbol.asyncIterator]}function c(e){if("function"!=typeof e)throw new Error("expected a function");return u(e)?r(e):e}function o(e,t=e.length){if(!t)throw new Error("arity is undefined");return function(...n){return"function"==typeof n[t-1]?e.apply(this,n):new Promise((a,i)=>{n[t-1]=(e,...t)=>e?i(e):void a(1<t.length?t:t[0]),e.apply(this,n)})}}function h(e){return function(t,...n){const a=o(function(a){var i=this;return e(t,(e,t)=>{c(e).apply(i,n.concat(t))},a)});return a}}function f(e,t,n,a){t=t||[];var i=[],r=0,s=c(n);return e(t,(e,t,n)=>{var a=r++;s(e,(e,t)=>{i[a]=t,n(e)})},e=>{a(e,i)})}function y(e){return e&&"number"==typeof e.length&&0<=e.length&&0==e.length%1}function m(e){function t(...t){if(null!==e){var n=e;e=null,n.apply(this,t)}}return Object.assign(t,e),t}function g(e){return e[Symbol.iterator]&&e[Symbol.iterator]()}function k(e){var t=-1,n=e.length;return function(){return++t<n?{value:e[t],key:t}:null}}function v(e){var t=-1;return function(){var n=e.next();return n.done?null:(t++,{value:n.value,key:t})}}function S(e){var t=e?Object.keys(e):[],n=-1,a=t.length;return function i(){var r=t[++n];return"__proto__"===r?i():n<a?{value:e[r],key:r}:null}}function x(e){if(y(e))return k(e);var t=g(e);return t?v(t):S(e)}function L(e){return function(...t){if(null===e)throw new Error("Callback was already called.");var n=e;e=null,n.apply(this,t)}}function E(e,t,n,a){function i(){p>=t||d||l||(d=!0,e.next().then(({value:e,done:t})=>{if(!(u||l))return d=!1,t?(l=!0,void(0>=p&&a(null))):void(p++,n(e,c,r),c++,i())}).catch(s))}function r(e,t){return p-=1,u?void 0:e?s(e):!1===e?(l=!0,void(u=!0)):t===be||l&&0>=p?(l=!0,a(null)):void i()}function s(e){u||(d=!1,l=!0,a(e))}let l=!1,u=!1,d=!1,p=0,c=0;i()}function O(e,t,n){function a(e,t){!1===e&&(l=!0);!0===l||(e?n(e):(++r===s||t===be)&&n(null))}n=m(n);var i=0,r=0,{length:s}=e,l=!1;for(0===s&&n(null);i<s;i++)t(e[i],i,L(a))}function _(e,t,n){return Ie(e,1/0,t,n)}function b(){function e(e,...a){return e?n(e):void t(1<a.length?a:a[0])}let t,n;return e[Ce]=new Promise((e,a)=>{t=e,n=a}),e}function A(e,t,n){function a(e,t){g.push(()=>l(e,t))}function i(){if(!h){if(0===g.length&&0===o)return n(null,p);for(;g.length&&o<t;){var e=g.shift();e()}}}function r(e,t){var n=y[e];n||(n=y[e]=[]),n.push(t)}function s(e){var t=y[e]||[];t.forEach(e=>e()),i()}function l(e,t){if(!f){var a=L((t,...a)=>{if(o--,!1===t)return void(h=!0);if(2>a.length&&([a]=a),t){var i={};if(Object.keys(p).forEach(e=>{i[e]=p[e]}),i[e]=a,f=!0,y=Object.create(null),h)return;n(t,i)}else p[e]=a,s(e)});o++;var i=c(t[t.length-1]);1<t.length?i(p,a):i(a)}}function u(t){var n=[];return Object.keys(e).forEach(a=>{const i=e[a];Array.isArray(i)&&0<=i.indexOf(t)&&n.push(a)}),n}"number"!=typeof t&&(n=t,t=null),n=m(n||b());var d=Object.keys(e).length;if(!d)return n(null);t||(t=d);var p={},o=0,h=!1,f=!1,y=Object.create(null),g=[],k=[],v={};return Object.keys(e).forEach(t=>{var n=e[t];if(!Array.isArray(n))return a(t,[n]),void k.push(t);var i=n.slice(0,n.length-1),s=i.length;return 0===s?(a(t,n),void k.push(t)):void(v[t]=s,i.forEach(l=>{if(!e[l])throw new Error("async.auto task `"+t+"` has a non-existent dependency `"+l+"` in "+i.join(", "));r(l,()=>{s--,0===s&&a(t,n)})}))}),function(){for(var e,t=0;k.length;)e=k.pop(),t++,u(e).forEach(e=>{0==--v[e]&&k.push(e)});if(t!==d)throw new Error("async.auto cannot execute tasks due to a recursive dependency")}(),i(),n[Ce]}function I(e){let t="",n=0,a=e.indexOf("*/");for(;n<e.length;)if("/"===e[n]&&"/"===e[n+1]){let t=e.indexOf("\n",n);n=-1===t?e.length:t}else if(-1!==a&&"/"===e[n]&&"*"===e[n+1]){let i=e.indexOf("*/",n);-1===i?(t+=e[n],n++):(n=i+2,a=e.indexOf("*/",n))}else t+=e[n],n++;return t}function M(e){const t=I(e.toString());let n=t.match(Pe);if(n||(n=t.match(Re)),!n)throw new Error("could not parse args in autoInject\nSource:\n"+t);let[,a]=n;return a.replace(/\s/g,"").split(ze).map(e=>e.replace(Ne,"").trim())}function j(e,t){var n={};return Object.keys(e).forEach(t=>{function a(e,t){var n=i.map(t=>e[t]);n.push(t),c(r)(...n)}var i,r=e[t],s=u(r),l=!s&&1===r.length||s&&0===r.length;if(Array.isArray(r))i=[...r],r=i.pop(),n[t]=i.concat(0<i.length?a:r);else if(l)n[t]=r;else{if(i=M(r),0===r.length&&!s&&0===i.length)throw new Error("autoInject task functions require explicit parameters.");s||i.pop(),n[t]=i.concat(a)}}),A(n,t)}function w(e,t){e.length=1,e.head=e.tail=t}function B(e,t,n){function a(e,t){f[e].push(t)}function i(e,t){const n=(...a)=>{r(e,n),t(...a)};f[e].push(n)}function r(e,t){return e?t?void(f[e]=f[e].filter(e=>e!==t)):f[e]=[]:Object.keys(f).forEach(e=>f[e]=[])}function s(e,...t){f[e].forEach(e=>e(...t))}function l(e,t,n,a){function i(e,...t){return e?n?s(e):r():1>=t.length?r(t[0]):void r(t)}if(null!=a&&"function"!=typeof a)throw new Error("task callback must be a function");k.started=!0;var r,s,l=k._createTaskItem(e,n?i:a||i);if(t?k._tasks.unshift(l):k._tasks.push(l),y||(y=!0,_e(()=>{y=!1,k.process()})),n||!a)return new Promise((e,t)=>{r=e,s=t})}function u(e){return function(t,...n){o-=1;for(var a=0,r=e.length;a<r;a++){var l=e[a],u=h.indexOf(l);0===u?h.shift():0<u&&h.splice(u,1),l.callback(t,...n),null!=t&&s("error",t,l.data)}o<=k.concurrency-k.buffer&&s("unsaturated"),k.idle()&&s("drain"),k.process()}}function d(e){return!!(0===e.length&&k.idle())&&(_e(()=>s("drain")),!0)}if(null==t)t=1;else if(0===t)throw new RangeError("Concurrency must not be zero");var p=c(e),o=0,h=[];const f={error:[],drain:[],saturated:[],unsaturated:[],empty:[]};var y=!1;const m=e=>t=>t?void(r(e),a(e,t)):new Promise((t,n)=>{i(e,(e,a)=>e?n(e):void t(a))});var g=!1,k={_tasks:new Ve,_createTaskItem(e,t){return{data:e,callback:t}},*[Symbol.iterator](){yield*k._tasks[Symbol.iterator]()},concurrency:t,payload:n,buffer:t/4,started:!1,paused:!1,push(e,t){return Array.isArray(e)?d(e)?void 0:e.map(e=>l(e,!1,!1,t)):l(e,!1,!1,t)},pushAsync(e,t){return Array.isArray(e)?d(e)?void 0:e.map(e=>l(e,!1,!0,t)):l(e,!1,!0,t)},kill(){r(),k._tasks.empty()},unshift(e,t){return Array.isArray(e)?d(e)?void 0:e.map(e=>l(e,!0,!1,t)):l(e,!0,!1,t)},unshiftAsync(e,t){return Array.isArray(e)?d(e)?void 0:e.map(e=>l(e,!0,!0,t)):l(e,!0,!0,t)},remove(e){k._tasks.remove(e)},process(){var e=Math.min;if(!g){for(g=!0;!k.paused&&o<k.concurrency&&k._tasks.length;){var t=[],n=[],a=k._tasks.length;k.payload&&(a=e(a,k.payload));for(var r,d=0;d<a;d++)r=k._tasks.shift(),t.push(r),h.push(r),n.push(r.data);o+=1,0===k._tasks.length&&s("empty"),o===k.concurrency&&s("saturated");var c=L(u(t));p(n,c)}g=!1}},length(){return k._tasks.length},running(){return o},workersList(){return h},idle(){return 0===k._tasks.length+o},pause(){k.paused=!0},resume(){!1===k.paused||(k.paused=!1,_e(k.process))}};return Object.defineProperties(k,{saturated:{writable:!1,value:m("saturated")},unsaturated:{writable:!1,value:m("unsaturated")},empty:{writable:!1,value:m("empty")},drain:{writable:!1,value:m("drain")},error:{writable:!1,value:m("error")}}),k}function T(e,t){return B(e,1,t)}function F(e,t,n){return B(e,t,n)}function C(...e){var t=e.map(c);return function(...e){var n=this,a=e[e.length-1];return"function"==typeof a?e.pop():a=b(),qe(t,e,(e,t,a)=>{t.apply(n,e.concat((e,...t)=>{a(e,t)}))},(e,t)=>a(e,...t)),a[Ce]}}function P(...e){return C(...e.reverse())}function R(...e){return function(...t){var n=t.pop();return n(null,...e)}}function z(e,t){return(n,a,i,r)=>{var s,l=!1;const u=c(i);n(a,(n,a,i)=>{u(n,(a,r)=>a||!1===a?i(a):e(r)&&!s?(l=!0,s=t(!0,n),i(null,be)):void i())},e=>e?r(e):void r(null,l?s:t(!1)))}}function N(e){return(t,...n)=>c(t)(...n,(t,...n)=>{"object"==typeof console&&(t?console.error&&console.error(t):console[e]&&n.forEach(t=>console[e](t)))})}function V(e,t,n){const a=c(t);return Xe(e,(...e)=>{const t=e.pop();a(...e,(e,n)=>t(e,!n))},n)}function Y(e){return(t,n,a)=>e(t,a)}function q(e){return u(e)?e:function(...t){var n=t.pop(),a=!0;t.push((...e)=>{a?_e(()=>n(...e)):n(...e)}),e.apply(this,t),a=!1}}function D(e,t,n,a){var r=Array(t.length);e(t,(e,t,a)=>{n(e,(e,n)=>{r[t]=!!n,a(e)})},e=>{if(e)return a(e);for(var n=[],s=0;s<t.length;s++)r[s]&&n.push(t[s]);a(null,n)})}function Q(e,t,n,a){var i=[];e(t,(e,t,a)=>{n(e,(n,r)=>n?a(n):void(r&&i.push({index:t,value:e}),a(n)))},e=>e?a(e):void a(null,i.sort((e,t)=>e.index-t.index).map(e=>e.value)))}function U(e,t,n,a){var i=y(t)?D:Q;return i(e,t,c(n),a)}function G(e,t,n){return ut(e,1/0,t,n)}function W(e,t,n){return ut(e,1,t,n)}function H(e,t,n){return pt(e,1/0,t,n)}function J(e,t,n){return pt(e,1,t,n)}function K(e,t=e=>e){var a=Object.create(null),r=Object.create(null),s=c(e),l=n((e,n)=>{var u=t(...e);u in a?_e(()=>n(null,...a[u])):u in r?r[u].push(n):(r[u]=[n],s(...e,(e,...t)=>{e||(a[u]=t);var n=r[u];delete r[u];for(var s=0,d=n.length;s<d;s++)n[s](e,...t)}))});return l.memo=a,l.unmemoized=e,l}function X(e,t){return ot(Me,e,t)}function Z(e,t,n){return ot(Ae(t),e,n)}function $(e,t){var n=c(e);return B((e,t)=>{n(e[0],t)},t,1)}function ee(e){return(e<<1)+1}function te(e){return(e+1>>1)-1}function ne(e,t){return e.priority===t.priority?e.pushCount<t.pushCount:e.priority<t.priority}function ae(e,t){function n(e,t){return Array.isArray(e)?e.map(e=>({data:e,priority:t})):{data:e,priority:t}}var a=$(e,t),{push:i,pushAsync:r}=a;return a._tasks=new ht,a._createTaskItem=({data:e,priority:t},n)=>({data:e,priority:t,callback:n}),a.push=function(e,t=0,a){return i(n(e,t),a)},a.pushAsync=function(e,t=0,a){return r(n(e,t),a)},delete a.unshift,delete a.unshiftAsync,a}function ie(e,t,n,a){var i=[...e].reverse();return qe(i,t,n,a)}function re(e){var t=c(e);return n(function(e,n){return e.push((e,...t)=>{let a={};if(e&&(a.error=e),0<t.length){var i=t;1>=t.length&&([i]=t),a.value=i}n(null,a)}),t.apply(this,e)})}function se(e){var t;return Array.isArray(e)?t=e.map(re):(t={},Object.keys(e).forEach(n=>{t[n]=re.call(this,e[n])})),t}function le(e,t,n,a){const i=c(n);return U(e,t,(e,t)=>{i(e,(e,n)=>{t(e,!n)})},a)}function ue(e){return function(){return e}}function de(e,t,n){function a(){r((e,...t)=>{!1===e||(e&&s++<i.times&&("function"!=typeof i.errorFilter||i.errorFilter(e))?setTimeout(a,i.intervalFunc(s-1)):n(e,...t))})}var i={times:kt,intervalFunc:ue(vt)};if(3>arguments.length&&"function"==typeof e?(n=t||b(),t=e):(pe(i,e),n=n||b()),"function"!=typeof t)throw new Error("Invalid arguments for async.retry");var r=c(t),s=1;return a(),n[Ce]}function pe(e,n){if("object"==typeof n)e.times=+n.times||kt,e.intervalFunc="function"==typeof n.interval?n.interval:ue(+n.interval||vt),e.errorFilter=n.errorFilter;else if("number"==typeof n||"string"==typeof n)e.times=+n||kt;else throw new Error("Invalid arguments for async.retry")}function ce(e,t){t||(t=e,e=null);let a=e&&e.arity||t.length;u(t)&&(a+=1);var i=c(t);return n((t,n)=>{function r(e){i(...t,e)}return(t.length<a-1||null==n)&&(t.push(n),n=b()),e?de(e,r,n):de(r,n),n[Ce]})}function oe(e,t){return ot(Be,e,t)}function he(e,t,a){var i=c(e);return n((n,r)=>{var s,l=!1;n.push((...e)=>{l||(r(...e),clearTimeout(s))}),s=setTimeout(function(){var t=e.name||"anonymous",n=new Error("Callback function \""+t+"\" timed out.");n.code="ETIMEDOUT",a&&(n.info=a),l=!0,r(n)},t),i(...n)})}function fe(e){for(var t=Array(e);e--;)t[e]=e;return t}function ye(e,t,n,a){var i=c(n);return De(fe(e),t,i,a)}function me(e,t,n){return ye(e,1/0,t,n)}function ge(e,t,n){return ye(e,1,t,n)}function ke(e,t,n,a){3>=arguments.length&&"function"==typeof t&&(a=n,n=t,t=Array.isArray(e)?[]:{}),a=m(a||b());var i=c(n);return Me(e,(e,n,a)=>{i(t,e,n,a)},e=>a(e,t)),a[Ce]}function ve(e){return(...t)=>(e.unmemoized||e)(...t)}function Se(e,t,n){const a=c(e);return _t(e=>a((t,n)=>e(t,!n)),t,n)}var xe,Le="function"==typeof queueMicrotask&&queueMicrotask,Ee="function"==typeof setImmediate&&setImmediate,Oe="object"==typeof process&&"function"==typeof process.nextTick;xe=Le?queueMicrotask:Ee?setImmediate:Oe?process.nextTick:a;var _e=i(xe);const be={};var Ae=e=>(t,n,a)=>{function i(e,t){if(!u)if(c-=1,e)l=!0,a(e);else if(!1===e)l=!0,u=!0;else{if(t===be||l&&0>=c)return l=!0,a(null);o||r()}}function r(){for(o=!0;c<e&&!l;){var t=s();if(null===t)return l=!0,void(0>=c&&a(null));c+=1,n(t.value,t.key,L(i))}o=!1}if(a=m(a),0>=e)throw new RangeError("concurrency limit cannot be less than 1");if(!t)return a(null);if(d(t))return E(t,e,n,a);if(p(t))return E(t[Symbol.asyncIterator](),e,n,a);var s=x(t),l=!1,u=!1,c=0,o=!1;r()},Ie=o(function(e,t,n,a){return Ae(t)(e,c(n),a)},4),Me=o(function(e,t,n){var a=y(e)?O:_;return a(e,c(t),n)},3),je=o(function(e,t,n){return f(Me,e,t,n)},3),we=h(je),Be=o(function(e,t,n){return Ie(e,1,t,n)},3),Te=o(function(e,t,n){return f(Be,e,t,n)},3),Fe=h(Te);const Ce=Symbol("promiseCallback");var Pe=/^(?:async\s+)?(?:function)?\s*\w*\s*\(\s*([^)]+)\s*\)(?:\s*{)/,Re=/^(?:async\s+)?\(?\s*([^)=]+)\s*\)?(?:\s*=>)/,ze=/,/,Ne=/(=.+)?(\s*)$/;class Ve{constructor(){this.head=this.tail=null,this.length=0}removeLink(e){return e.prev?e.prev.next=e.next:this.head=e.next,e.next?e.next.prev=e.prev:this.tail=e.prev,e.prev=e.next=null,this.length-=1,e}empty(){for(;this.head;)this.shift();return this}insertAfter(e,t){t.prev=e,t.next=e.next,e.next?e.next.prev=t:this.tail=t,e.next=t,this.length+=1}insertBefore(e,t){t.prev=e.prev,t.next=e,e.prev?e.prev.next=t:this.head=t,e.prev=t,this.length+=1}unshift(e){this.head?this.insertBefore(this.head,e):w(this,e)}push(e){this.tail?this.insertAfter(this.tail,e):w(this,e)}shift(){return this.head&&this.removeLink(this.head)}pop(){return this.tail&&this.removeLink(this.tail)}toArray(){return[...this]}*[Symbol.iterator](){for(var e=this.head;e;)yield e.data,e=e.next}remove(e){for(var t=this.head;t;){var{next:n}=t;e(t)&&this.removeLink(t),t=n}return this}}var Ye,qe=o(function(e,t,n,a){a=m(a);var r=c(n);return Be(e,(e,n,a)=>{r(t,e,(e,n)=>{t=n,a(e)})},e=>a(e,t))},4),De=o(function(e,t,n,a){return f(Ae(t),e,n,a)},4),Qe=o(function(e,t,n,a){var i=c(n);return De(e,t,(e,t)=>{i(e,(e,...n)=>e?t(e):t(e,n))},(e,t)=>{for(var n=[],r=0;r<t.length;r++)t[r]&&(n=n.concat(...t[r]));return a(e,n)})},4),Ue=o(function(e,t,n){return Qe(e,1/0,t,n)},3),Ge=o(function(e,t,n){return Qe(e,1,t,n)},3),We=o(function(e,t,n){return z(e=>e,(e,t)=>t)(Me,e,t,n)},3),He=o(function(e,t,n,a){return z(e=>e,(e,t)=>t)(Ae(t),e,n,a)},4),Je=o(function(e,t,n){return z(e=>e,(e,t)=>t)(Ae(1),e,t,n)},3),Ke=N("dir"),Xe=o(function(e,t,n){function a(e,...t){return e?n(e):void(!1===e||(r=t,l(...t,i)))}function i(e,t){return e?n(e):!1===e?void 0:t?void s(a):n(null,...r)}n=L(n);var r,s=c(e),l=c(t);return i(null,!0)},3),Ze=o(function(e,t,n){return Me(e,Y(c(t)),n)},3),$e=o(function(e,t,n,a){return Ae(t)(e,Y(c(n)),a)},4),et=o(function(e,t,n){return $e(e,1,t,n)},3),tt=o(function(e,t,n){return z(e=>!e,e=>!e)(Me,e,t,n)},3),nt=o(function(e,t,n,a){return z(e=>!e,e=>!e)(Ae(t),e,n,a)},4),at=o(function(e,t,n){return z(e=>!e,e=>!e)(Be,e,t,n)},3),it=o(function(e,t,n){return U(Me,e,t,n)},3),rt=o(function(e,t,n,a){return U(Ae(t),e,n,a)},4),st=o(function(e,t,n){return U(Be,e,t,n)},3),lt=o(function(e,t){function n(e){return e?a(e):void(!1===e||i(n))}var a=L(t),i=c(q(e));return n()},2),ut=o(function(e,t,n,a){var i=c(n);return De(e,t,(e,t)=>{i(e,(n,a)=>n?t(n):t(n,{key:a,val:e}))},(e,t)=>{for(var n={},{hasOwnProperty:r}=Object.prototype,s=0;s<t.length;s++)if(t[s]){var{key:l}=t[s],{val:u}=t[s];r.call(n,l)?n[l].push(u):n[l]=[u]}return a(e,n)})},4),dt=N("log"),pt=o(function(e,t,n,a){a=m(a);var i={},r=c(n);return Ae(t)(e,(e,t,n)=>{r(e,t,(e,a)=>e?n(e):void(i[t]=a,n(e)))},e=>a(e,i))},4);Ye=Oe?process.nextTick:Ee?setImmediate:a;var ct=i(Ye),ot=o((e,t,n)=>{var a=y(t)?[]:{};e(t,(e,t,n)=>{c(e)((e,...i)=>{2>i.length&&([i]=i),a[t]=i,n(e)})},e=>n(e,a))},3);class ht{constructor(){this.heap=[],this.pushCount=Number.MIN_SAFE_INTEGER}get length(){return this.heap.length}empty(){return this.heap=[],this}percUp(e){for(let n;0<e&&ne(this.heap[e],this.heap[n=te(e)]);){let a=this.heap[e];this.heap[e]=this.heap[n],this.heap[n]=a,e=n}}percDown(e){for(let n,a;(n=ee(e))<this.heap.length&&(n+1<this.heap.length&&ne(this.heap[n+1],this.heap[n])&&++n,!ne(this.heap[e],this.heap[n]));)a=this.heap[e],this.heap[e]=this.heap[n],this.heap[n]=a,e=n}push(e){e.pushCount=++this.pushCount,this.heap.push(e),this.percUp(this.heap.length-1)}unshift(e){return this.heap.push(e)}shift(){let[e]=this.heap;return this.heap[0]=this.heap[this.heap.length-1],this.heap.pop(),this.percDown(0),e}toArray(){return[...this]}*[Symbol.iterator](){for(let e=0;e<this.heap.length;e++)yield this.heap[e].data}remove(e){let t=0;for(let n=0;n<this.heap.length;n++)e(this.heap[n])||(this.heap[t]=this.heap[n],t++);this.heap.splice(t);for(let t=te(this.heap.length-1);0<=t;t--)this.percDown(t);return this}}var ft=o(function(e,t){if(t=m(t),!Array.isArray(e))return t(new TypeError("First argument to race must be an array of functions"));if(!e.length)return t();for(var n=0,a=e.length;n<a;n++)c(e[n])(t)},2),yt=o(function(e,t,n){return le(Me,e,t,n)},3),mt=o(function(e,t,n,a){return le(Ae(t),e,n,a)},4),gt=o(function(e,t,n){return le(Be,e,t,n)},3);const kt=5,vt=0;var St=o(function(e,t,n){return z(Boolean,e=>e)(Me,e,t,n)},3),xt=o(function(e,t,n,a){return z(Boolean,e=>e)(Ae(t),e,n,a)},4),Lt=o(function(e,t,n){return z(Boolean,e=>e)(Be,e,t,n)},3),Et=o(function(e,t,n){function a(e,t){var n=e.criteria,a=t.criteria;return n<a?-1:n>a?1:0}var i=c(t);return je(e,(e,t)=>{i(e,(n,a)=>n?t(n):void t(n,{value:e,criteria:a}))},(e,t)=>e?n(e):void n(null,t.sort(a).map(e=>e.value)))},3),Ot=o(function(e,t){var n,a=null;return et(e,(e,t)=>{c(e)((e,...i)=>!1===e?t(e):void(2>i.length?[n]=i:n=i,a=e,t(e?null:{})))},()=>t(a,n))}),_t=o(function(e,t,n){function a(e,...t){if(e)return n(e);l=t;!1===e||s(i)}function i(e,t){return e?n(e):!1===e?void 0:t?void r(a):n(null,...l)}n=L(n);var r=c(t),s=c(e),l=[];return s(i)},3),bt=o(function(e,t){function n(t){var n=c(e[i++]);n(...t,L(a))}function a(a,...r){return!1===a?void 0:a||i===e.length?t(a,...r):void n(r)}if(t=m(t),!Array.isArray(e))return t(new Error("First argument to waterfall must be an array of functions"));if(!e.length)return t();var i=0;n([])});e.default={apply:t,applyEach:we,applyEachSeries:Fe,asyncify:r,auto:A,autoInject:j,cargo:T,cargoQueue:F,compose:P,concat:Ue,concatLimit:Qe,concatSeries:Ge,constant:R,detect:We,detectLimit:He,detectSeries:Je,dir:Ke,doUntil:V,doWhilst:Xe,each:Ze,eachLimit:$e,eachOf:Me,eachOfLimit:Ie,eachOfSeries:Be,eachSeries:et,ensureAsync:q,every:tt,everyLimit:nt,everySeries:at,filter:it,filterLimit:rt,filterSeries:st,forever:lt,groupBy:G,groupByLimit:ut,groupBySeries:W,log:dt,map:je,mapLimit:De,mapSeries:Te,mapValues:H,mapValuesLimit:pt,mapValuesSeries:J,memoize:K,nextTick:ct,parallel:X,parallelLimit:Z,priorityQueue:ae,queue:$,race:ft,reduce:qe,reduceRight:ie,reflect:re,reflectAll:se,reject:yt,rejectLimit:mt,rejectSeries:gt,retry:de,retryable:ce,seq:C,series:oe,setImmediate:_e,some:St,someLimit:xt,someSeries:Lt,sortBy:Et,timeout:he,times:me,timesLimit:ye,timesSeries:ge,transform:ke,tryEach:Ot,unmemoize:ve,until:Se,waterfall:bt,whilst:_t,all:tt,allLimit:nt,allSeries:at,any:St,anyLimit:xt,anySeries:Lt,find:We,findLimit:He,findSeries:Je,flatMap:Ue,flatMapLimit:Qe,flatMapSeries:Ge,forEach:Ze,forEachSeries:et,forEachLimit:$e,forEachOf:Me,forEachOfSeries:Be,forEachOfLimit:Ie,inject:qe,foldl:qe,foldr:ie,select:it,selectLimit:rt,selectSeries:st,wrapSync:r,during:_t,doDuring:Xe},e.apply=t,e.applyEach=we,e.applyEachSeries=Fe,e.asyncify=r,e.auto=A,e.autoInject=j,e.cargo=T,e.cargoQueue=F,e.compose=P,e.concat=Ue,e.concatLimit=Qe,e.concatSeries=Ge,e.constant=R,e.detect=We,e.detectLimit=He,e.detectSeries=Je,e.dir=Ke,e.doUntil=V,e.doWhilst=Xe,e.each=Ze,e.eachLimit=$e,e.eachOf=Me,e.eachOfLimit=Ie,e.eachOfSeries=Be,e.eachSeries=et,e.ensureAsync=q,e.every=tt,e.everyLimit=nt,e.everySeries=at,e.filter=it,e.filterLimit=rt,e.filterSeries=st,e.forever=lt,e.groupBy=G,e.groupByLimit=ut,e.groupBySeries=W,e.log=dt,e.map=je,e.mapLimit=De,e.mapSeries=Te,e.mapValues=H,e.mapValuesLimit=pt,e.mapValuesSeries=J,e.memoize=K,e.nextTick=ct,e.parallel=X,e.parallelLimit=Z,e.priorityQueue=ae,e.queue=$,e.race=ft,e.reduce=qe,e.reduceRight=ie,e.reflect=re,e.reflectAll=se,e.reject=yt,e.rejectLimit=mt,e.rejectSeries=gt,e.retry=de,e.retryable=ce,e.seq=C,e.series=oe,e.setImmediate=_e,e.some=St,e.someLimit=xt,e.someSeries=Lt,e.sortBy=Et,e.timeout=he,e.times=me,e.timesLimit=ye,e.timesSeries=ge,e.transform=ke,e.tryEach=Ot,e.unmemoize=ve,e.until=Se,e.waterfall=bt,e.whilst=_t,e.all=tt,e.allLimit=nt,e.allSeries=at,e.any=St,e.anyLimit=xt,e.anySeries=Lt,e.find=We,e.findLimit=He,e.findSeries=Je,e.flatMap=Ue,e.flatMapLimit=Qe,e.flatMapSeries=Ge,e.forEach=Ze,e.forEachSeries=et,e.forEachLimit=$e,e.forEachOf=Me,e.forEachOfSeries=Be,e.forEachOfLimit=Ie,e.inject=qe,e.foldl=qe,e.foldr=ie,e.select=it,e.selectLimit=rt,e.selectSeries=st,e.wrapSync=r,e.during=_t,e.doDuring=Xe,Object.defineProperty(e,"__esModule",{value:!0})});
\ No newline at end of file
diff --git a/node_modules/async/dist/async.mjs b/node_modules/async/dist/async.mjs
new file mode 100644
index 0000000000000000000000000000000000000000..d0cd59d969fb3f69993ab8403b301be18953a3b1
--- /dev/null
+++ b/node_modules/async/dist/async.mjs
@@ -0,0 +1,5947 @@
+/**
+ * Creates a continuation function with some arguments already applied.
+ *
+ * Useful as a shorthand when combined with other control flow functions. Any
+ * arguments passed to the returned function are added to the arguments
+ * originally passed to apply.
+ *
+ * @name apply
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {Function} fn - The function you want to eventually apply all
+ * arguments to. Invokes with (arguments...).
+ * @param {...*} arguments... - Any number of arguments to automatically apply
+ * when the continuation is called.
+ * @returns {Function} the partially-applied function
+ * @example
+ *
+ * // using apply
+ * async.parallel([
+ *     async.apply(fs.writeFile, 'testfile1', 'test1'),
+ *     async.apply(fs.writeFile, 'testfile2', 'test2')
+ * ]);
+ *
+ *
+ * // the same process without using apply
+ * async.parallel([
+ *     function(callback) {
+ *         fs.writeFile('testfile1', 'test1', callback);
+ *     },
+ *     function(callback) {
+ *         fs.writeFile('testfile2', 'test2', callback);
+ *     }
+ * ]);
+ *
+ * // It's possible to pass any number of additional arguments when calling the
+ * // continuation:
+ *
+ * node> var fn = async.apply(sys.puts, 'one');
+ * node> fn('two', 'three');
+ * one
+ * two
+ * three
+ */
+function apply(fn, ...args) {
+    return (...callArgs) => fn(...args,...callArgs);
+}
+
+function initialParams (fn) {
+    return function (...args/*, callback*/) {
+        var callback = args.pop();
+        return fn.call(this, args, callback);
+    };
+}
+
+/* istanbul ignore file */
+
+var hasQueueMicrotask = typeof queueMicrotask === 'function' && queueMicrotask;
+var hasSetImmediate = typeof setImmediate === 'function' && setImmediate;
+var hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function';
+
+function fallback(fn) {
+    setTimeout(fn, 0);
+}
+
+function wrap(defer) {
+    return (fn, ...args) => defer(() => fn(...args));
+}
+
+var _defer;
+
+if (hasQueueMicrotask) {
+    _defer = queueMicrotask;
+} else if (hasSetImmediate) {
+    _defer = setImmediate;
+} else if (hasNextTick) {
+    _defer = process.nextTick;
+} else {
+    _defer = fallback;
+}
+
+var setImmediate$1 = wrap(_defer);
+
+/**
+ * Take a sync function and make it async, passing its return value to a
+ * callback. This is useful for plugging sync functions into a waterfall,
+ * series, or other async functions. Any arguments passed to the generated
+ * function will be passed to the wrapped function (except for the final
+ * callback argument). Errors thrown will be passed to the callback.
+ *
+ * If the function passed to `asyncify` returns a Promise, that promises's
+ * resolved/rejected state will be used to call the callback, rather than simply
+ * the synchronous return value.
+ *
+ * This also means you can asyncify ES2017 `async` functions.
+ *
+ * @name asyncify
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @alias wrapSync
+ * @category Util
+ * @param {Function} func - The synchronous function, or Promise-returning
+ * function to convert to an {@link AsyncFunction}.
+ * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be
+ * invoked with `(args..., callback)`.
+ * @example
+ *
+ * // passing a regular synchronous function
+ * async.waterfall([
+ *     async.apply(fs.readFile, filename, "utf8"),
+ *     async.asyncify(JSON.parse),
+ *     function (data, next) {
+ *         // data is the result of parsing the text.
+ *         // If there was a parsing error, it would have been caught.
+ *     }
+ * ], callback);
+ *
+ * // passing a function returning a promise
+ * async.waterfall([
+ *     async.apply(fs.readFile, filename, "utf8"),
+ *     async.asyncify(function (contents) {
+ *         return db.model.create(contents);
+ *     }),
+ *     function (model, next) {
+ *         // `model` is the instantiated model object.
+ *         // If there was an error, this function would be skipped.
+ *     }
+ * ], callback);
+ *
+ * // es2017 example, though `asyncify` is not needed if your JS environment
+ * // supports async functions out of the box
+ * var q = async.queue(async.asyncify(async function(file) {
+ *     var intermediateStep = await processFile(file);
+ *     return await somePromise(intermediateStep)
+ * }));
+ *
+ * q.push(files);
+ */
+function asyncify(func) {
+    if (isAsync(func)) {
+        return function (...args/*, callback*/) {
+            const callback = args.pop();
+            const promise = func.apply(this, args);
+            return handlePromise(promise, callback)
+        }
+    }
+
+    return initialParams(function (args, callback) {
+        var result;
+        try {
+            result = func.apply(this, args);
+        } catch (e) {
+            return callback(e);
+        }
+        // if result is Promise object
+        if (result && typeof result.then === 'function') {
+            return handlePromise(result, callback)
+        } else {
+            callback(null, result);
+        }
+    });
+}
+
+function handlePromise(promise, callback) {
+    return promise.then(value => {
+        invokeCallback(callback, null, value);
+    }, err => {
+        invokeCallback(callback, err && err.message ? err : new Error(err));
+    });
+}
+
+function invokeCallback(callback, error, value) {
+    try {
+        callback(error, value);
+    } catch (err) {
+        setImmediate$1(e => { throw e }, err);
+    }
+}
+
+function isAsync(fn) {
+    return fn[Symbol.toStringTag] === 'AsyncFunction';
+}
+
+function isAsyncGenerator(fn) {
+    return fn[Symbol.toStringTag] === 'AsyncGenerator';
+}
+
+function isAsyncIterable(obj) {
+    return typeof obj[Symbol.asyncIterator] === 'function';
+}
+
+function wrapAsync(asyncFn) {
+    if (typeof asyncFn !== 'function') throw new Error('expected a function')
+    return isAsync(asyncFn) ? asyncify(asyncFn) : asyncFn;
+}
+
+// conditionally promisify a function.
+// only return a promise if a callback is omitted
+function awaitify (asyncFn, arity = asyncFn.length) {
+    if (!arity) throw new Error('arity is undefined')
+    function awaitable (...args) {
+        if (typeof args[arity - 1] === 'function') {
+            return asyncFn.apply(this, args)
+        }
+
+        return new Promise((resolve, reject) => {
+            args[arity - 1] = (err, ...cbArgs) => {
+                if (err) return reject(err)
+                resolve(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
+            };
+            asyncFn.apply(this, args);
+        })
+    }
+
+    return awaitable
+}
+
+function applyEach (eachfn) {
+    return function applyEach(fns, ...callArgs) {
+        const go = awaitify(function (callback) {
+            var that = this;
+            return eachfn(fns, (fn, cb) => {
+                wrapAsync(fn).apply(that, callArgs.concat(cb));
+            }, callback);
+        });
+        return go;
+    };
+}
+
+function _asyncMap(eachfn, arr, iteratee, callback) {
+    arr = arr || [];
+    var results = [];
+    var counter = 0;
+    var _iteratee = wrapAsync(iteratee);
+
+    return eachfn(arr, (value, _, iterCb) => {
+        var index = counter++;
+        _iteratee(value, (err, v) => {
+            results[index] = v;
+            iterCb(err);
+        });
+    }, err => {
+        callback(err, results);
+    });
+}
+
+function isArrayLike(value) {
+    return value &&
+        typeof value.length === 'number' &&
+        value.length >= 0 &&
+        value.length % 1 === 0;
+}
+
+// A temporary value used to identify if the loop should be broken.
+// See #1064, #1293
+const breakLoop = {};
+
+function once(fn) {
+    function wrapper (...args) {
+        if (fn === null) return;
+        var callFn = fn;
+        fn = null;
+        callFn.apply(this, args);
+    }
+    Object.assign(wrapper, fn);
+    return wrapper
+}
+
+function getIterator (coll) {
+    return coll[Symbol.iterator] && coll[Symbol.iterator]();
+}
+
+function createArrayIterator(coll) {
+    var i = -1;
+    var len = coll.length;
+    return function next() {
+        return ++i < len ? {value: coll[i], key: i} : null;
+    }
+}
+
+function createES2015Iterator(iterator) {
+    var i = -1;
+    return function next() {
+        var item = iterator.next();
+        if (item.done)
+            return null;
+        i++;
+        return {value: item.value, key: i};
+    }
+}
+
+function createObjectIterator(obj) {
+    var okeys = obj ? Object.keys(obj) : [];
+    var i = -1;
+    var len = okeys.length;
+    return function next() {
+        var key = okeys[++i];
+        if (key === '__proto__') {
+            return next();
+        }
+        return i < len ? {value: obj[key], key} : null;
+    };
+}
+
+function createIterator(coll) {
+    if (isArrayLike(coll)) {
+        return createArrayIterator(coll);
+    }
+
+    var iterator = getIterator(coll);
+    return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll);
+}
+
+function onlyOnce(fn) {
+    return function (...args) {
+        if (fn === null) throw new Error("Callback was already called.");
+        var callFn = fn;
+        fn = null;
+        callFn.apply(this, args);
+    };
+}
+
+// for async generators
+function asyncEachOfLimit(generator, limit, iteratee, callback) {
+    let done = false;
+    let canceled = false;
+    let awaiting = false;
+    let running = 0;
+    let idx = 0;
+
+    function replenish() {
+        //console.log('replenish')
+        if (running >= limit || awaiting || done) return
+        //console.log('replenish awaiting')
+        awaiting = true;
+        generator.next().then(({value, done: iterDone}) => {
+            //console.log('got value', value)
+            if (canceled || done) return
+            awaiting = false;
+            if (iterDone) {
+                done = true;
+                if (running <= 0) {
+                    //console.log('done nextCb')
+                    callback(null);
+                }
+                return;
+            }
+            running++;
+            iteratee(value, idx, iterateeCallback);
+            idx++;
+            replenish();
+        }).catch(handleError);
+    }
+
+    function iterateeCallback(err, result) {
+        //console.log('iterateeCallback')
+        running -= 1;
+        if (canceled) return
+        if (err) return handleError(err)
+
+        if (err === false) {
+            done = true;
+            canceled = true;
+            return
+        }
+
+        if (result === breakLoop || (done && running <= 0)) {
+            done = true;
+            //console.log('done iterCb')
+            return callback(null);
+        }
+        replenish();
+    }
+
+    function handleError(err) {
+        if (canceled) return
+        awaiting = false;
+        done = true;
+        callback(err);
+    }
+
+    replenish();
+}
+
+var eachOfLimit = (limit) => {
+    return (obj, iteratee, callback) => {
+        callback = once(callback);
+        if (limit <= 0) {
+            throw new RangeError('concurrency limit cannot be less than 1')
+        }
+        if (!obj) {
+            return callback(null);
+        }
+        if (isAsyncGenerator(obj)) {
+            return asyncEachOfLimit(obj, limit, iteratee, callback)
+        }
+        if (isAsyncIterable(obj)) {
+            return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback)
+        }
+        var nextElem = createIterator(obj);
+        var done = false;
+        var canceled = false;
+        var running = 0;
+        var looping = false;
+
+        function iterateeCallback(err, value) {
+            if (canceled) return
+            running -= 1;
+            if (err) {
+                done = true;
+                callback(err);
+            }
+            else if (err === false) {
+                done = true;
+                canceled = true;
+            }
+            else if (value === breakLoop || (done && running <= 0)) {
+                done = true;
+                return callback(null);
+            }
+            else if (!looping) {
+                replenish();
+            }
+        }
+
+        function replenish () {
+            looping = true;
+            while (running < limit && !done) {
+                var elem = nextElem();
+                if (elem === null) {
+                    done = true;
+                    if (running <= 0) {
+                        callback(null);
+                    }
+                    return;
+                }
+                running += 1;
+                iteratee(elem.value, elem.key, onlyOnce(iterateeCallback));
+            }
+            looping = false;
+        }
+
+        replenish();
+    };
+};
+
+/**
+ * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name eachOfLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.eachOf]{@link module:Collections.eachOf}
+ * @alias forEachOfLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each
+ * item in `coll`. The `key` is the item's key, or index in the case of an
+ * array.
+ * Invoked with (item, key, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachOfLimit$1(coll, limit, iteratee, callback) {
+    return eachOfLimit(limit)(coll, wrapAsync(iteratee), callback);
+}
+
+var eachOfLimit$2 = awaitify(eachOfLimit$1, 4);
+
+// eachOf implementation optimized for array-likes
+function eachOfArrayLike(coll, iteratee, callback) {
+    callback = once(callback);
+    var index = 0,
+        completed = 0,
+        {length} = coll,
+        canceled = false;
+    if (length === 0) {
+        callback(null);
+    }
+
+    function iteratorCallback(err, value) {
+        if (err === false) {
+            canceled = true;
+        }
+        if (canceled === true) return
+        if (err) {
+            callback(err);
+        } else if ((++completed === length) || value === breakLoop) {
+            callback(null);
+        }
+    }
+
+    for (; index < length; index++) {
+        iteratee(coll[index], index, onlyOnce(iteratorCallback));
+    }
+}
+
+// a generic version of eachOf which can handle array, object, and iterator cases.
+function eachOfGeneric (coll, iteratee, callback) {
+    return eachOfLimit$2(coll, Infinity, iteratee, callback);
+}
+
+/**
+ * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument
+ * to the iteratee.
+ *
+ * @name eachOf
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias forEachOf
+ * @category Collection
+ * @see [async.each]{@link module:Collections.each}
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each
+ * item in `coll`.
+ * The `key` is the item's key, or index in the case of an array.
+ * Invoked with (item, key, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * // dev.json is a file containing a valid json object config for dev environment
+ * // dev.json is a file containing a valid json object config for test environment
+ * // prod.json is a file containing a valid json object config for prod environment
+ * // invalid.json is a file with a malformed json object
+ *
+ * let configs = {}; //global variable
+ * let validConfigFileMap = {dev: 'dev.json', test: 'test.json', prod: 'prod.json'};
+ * let invalidConfigFileMap = {dev: 'dev.json', test: 'test.json', invalid: 'invalid.json'};
+ *
+ * // asynchronous function that reads a json file and parses the contents as json object
+ * function parseFile(file, key, callback) {
+ *     fs.readFile(file, "utf8", function(err, data) {
+ *         if (err) return calback(err);
+ *         try {
+ *             configs[key] = JSON.parse(data);
+ *         } catch (e) {
+ *             return callback(e);
+ *         }
+ *         callback();
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.forEachOf(validConfigFileMap, parseFile, function (err) {
+ *     if (err) {
+ *         console.error(err);
+ *     } else {
+ *         console.log(configs);
+ *         // configs is now a map of JSON data, e.g.
+ *         // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+ *     }
+ * });
+ *
+ * //Error handing
+ * async.forEachOf(invalidConfigFileMap, parseFile, function (err) {
+ *     if (err) {
+ *         console.error(err);
+ *         // JSON parse error exception
+ *     } else {
+ *         console.log(configs);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.forEachOf(validConfigFileMap, parseFile)
+ * .then( () => {
+ *     console.log(configs);
+ *     // configs is now a map of JSON data, e.g.
+ *     // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+ * }).catch( err => {
+ *     console.error(err);
+ * });
+ *
+ * //Error handing
+ * async.forEachOf(invalidConfigFileMap, parseFile)
+ * .then( () => {
+ *     console.log(configs);
+ * }).catch( err => {
+ *     console.error(err);
+ *     // JSON parse error exception
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.forEachOf(validConfigFileMap, parseFile);
+ *         console.log(configs);
+ *         // configs is now a map of JSON data, e.g.
+ *         // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * //Error handing
+ * async () => {
+ *     try {
+ *         let result = await async.forEachOf(invalidConfigFileMap, parseFile);
+ *         console.log(configs);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // JSON parse error exception
+ *     }
+ * }
+ *
+ */
+function eachOf(coll, iteratee, callback) {
+    var eachOfImplementation = isArrayLike(coll) ? eachOfArrayLike : eachOfGeneric;
+    return eachOfImplementation(coll, wrapAsync(iteratee), callback);
+}
+
+var eachOf$1 = awaitify(eachOf, 3);
+
+/**
+ * Produces a new collection of values by mapping each value in `coll` through
+ * the `iteratee` function. The `iteratee` is called with an item from `coll`
+ * and a callback for when it has finished processing. Each of these callbacks
+ * takes 2 arguments: an `error`, and the transformed item from `coll`. If
+ * `iteratee` passes an error to its callback, the main `callback` (for the
+ * `map` function) is immediately called with the error.
+ *
+ * Note, that since this function applies the `iteratee` to each item in
+ * parallel, there is no guarantee that the `iteratee` functions will complete
+ * in order. However, the results array will be in the same order as the
+ * original `coll`.
+ *
+ * If `map` is passed an Object, the results will be an Array.  The results
+ * will roughly be in the order of the original Objects' keys (but this can
+ * vary across JavaScript engines).
+ *
+ * @name map
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with the transformed item.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Results is an Array of the
+ * transformed items from the `coll`. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ * // file4.txt does not exist
+ *
+ * const fileList = ['file1.txt','file2.txt','file3.txt'];
+ * const withMissingFileList = ['file1.txt','file2.txt','file4.txt'];
+ *
+ * // asynchronous function that returns the file size in bytes
+ * function getFileSizeInBytes(file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.map(fileList, getFileSizeInBytes, function(err, results) {
+ *     if (err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(results);
+ *         // results is now an array of the file size in bytes for each file, e.g.
+ *         // [ 1000, 2000, 3000]
+ *     }
+ * });
+ *
+ * // Error Handling
+ * async.map(withMissingFileList, getFileSizeInBytes, function(err, results) {
+ *     if (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     } else {
+ *         console.log(results);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.map(fileList, getFileSizeInBytes)
+ * .then( results => {
+ *     console.log(results);
+ *     // results is now an array of the file size in bytes for each file, e.g.
+ *     // [ 1000, 2000, 3000]
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.map(withMissingFileList, getFileSizeInBytes)
+ * .then( results => {
+ *     console.log(results);
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.map(fileList, getFileSizeInBytes);
+ *         console.log(results);
+ *         // results is now an array of the file size in bytes for each file, e.g.
+ *         // [ 1000, 2000, 3000]
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let results = await async.map(withMissingFileList, getFileSizeInBytes);
+ *         console.log(results);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function map (coll, iteratee, callback) {
+    return _asyncMap(eachOf$1, coll, iteratee, callback)
+}
+var map$1 = awaitify(map, 3);
+
+/**
+ * Applies the provided arguments to each function in the array, calling
+ * `callback` after all functions have completed. If you only provide the first
+ * argument, `fns`, then it will return a function which lets you pass in the
+ * arguments as if it were a single function call. If more arguments are
+ * provided, `callback` is required while `args` is still optional. The results
+ * for each of the applied async functions are passed to the final callback
+ * as an array.
+ *
+ * @name applyEach
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s
+ * to all call with the same arguments
+ * @param {...*} [args] - any number of separate arguments to pass to the
+ * function.
+ * @param {Function} [callback] - the final argument should be the callback,
+ * called when all functions have completed processing.
+ * @returns {AsyncFunction} - Returns a function that takes no args other than
+ * an optional callback, that is the result of applying the `args` to each
+ * of the functions.
+ * @example
+ *
+ * const appliedFn = async.applyEach([enableSearch, updateSchema], 'bucket')
+ *
+ * appliedFn((err, results) => {
+ *     // results[0] is the results for `enableSearch`
+ *     // results[1] is the results for `updateSchema`
+ * });
+ *
+ * // partial application example:
+ * async.each(
+ *     buckets,
+ *     async (bucket) => async.applyEach([enableSearch, updateSchema], bucket)(),
+ *     callback
+ * );
+ */
+var applyEach$1 = applyEach(map$1);
+
+/**
+ * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time.
+ *
+ * @name eachOfSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.eachOf]{@link module:Collections.eachOf}
+ * @alias forEachOfSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * Invoked with (item, key, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachOfSeries(coll, iteratee, callback) {
+    return eachOfLimit$2(coll, 1, iteratee, callback)
+}
+var eachOfSeries$1 = awaitify(eachOfSeries, 3);
+
+/**
+ * The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time.
+ *
+ * @name mapSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.map]{@link module:Collections.map}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with the transformed item.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Results is an array of the
+ * transformed items from the `coll`. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function mapSeries (coll, iteratee, callback) {
+    return _asyncMap(eachOfSeries$1, coll, iteratee, callback)
+}
+var mapSeries$1 = awaitify(mapSeries, 3);
+
+/**
+ * The same as [`applyEach`]{@link module:ControlFlow.applyEach} but runs only a single async operation at a time.
+ *
+ * @name applyEachSeries
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.applyEach]{@link module:ControlFlow.applyEach}
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} fns - A collection of {@link AsyncFunction}s to all
+ * call with the same arguments
+ * @param {...*} [args] - any number of separate arguments to pass to the
+ * function.
+ * @param {Function} [callback] - the final argument should be the callback,
+ * called when all functions have completed processing.
+ * @returns {AsyncFunction} - A function, that when called, is the result of
+ * appling the `args` to the list of functions.  It takes no args, other than
+ * a callback.
+ */
+var applyEachSeries = applyEach(mapSeries$1);
+
+const PROMISE_SYMBOL = Symbol('promiseCallback');
+
+function promiseCallback () {
+    let resolve, reject;
+    function callback (err, ...args) {
+        if (err) return reject(err)
+        resolve(args.length > 1 ? args : args[0]);
+    }
+
+    callback[PROMISE_SYMBOL] = new Promise((res, rej) => {
+        resolve = res,
+        reject = rej;
+    });
+
+    return callback
+}
+
+/**
+ * Determines the best order for running the {@link AsyncFunction}s in `tasks`, based on
+ * their requirements. Each function can optionally depend on other functions
+ * being completed first, and each function is run as soon as its requirements
+ * are satisfied.
+ *
+ * If any of the {@link AsyncFunction}s pass an error to their callback, the `auto` sequence
+ * will stop. Further tasks will not execute (so any other functions depending
+ * on it will not run), and the main `callback` is immediately called with the
+ * error.
+ *
+ * {@link AsyncFunction}s also receive an object containing the results of functions which
+ * have completed so far as the first argument, if they have dependencies. If a
+ * task function has no dependencies, it will only be passed a callback.
+ *
+ * @name auto
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Object} tasks - An object. Each of its properties is either a
+ * function or an array of requirements, with the {@link AsyncFunction} itself the last item
+ * in the array. The object's key of a property serves as the name of the task
+ * defined by that property, i.e. can be used when specifying requirements for
+ * other tasks. The function receives one or two arguments:
+ * * a `results` object, containing the results of the previously executed
+ *   functions, only passed if the task has any dependencies,
+ * * a `callback(err, result)` function, which must be called when finished,
+ *   passing an `error` (which can be `null`) and the result of the function's
+ *   execution.
+ * @param {number} [concurrency=Infinity] - An optional `integer` for
+ * determining the maximum number of tasks that can be run in parallel. By
+ * default, as many as possible.
+ * @param {Function} [callback] - An optional callback which is called when all
+ * the tasks have been completed. It receives the `err` argument if any `tasks`
+ * pass an error to their callback. Results are always returned; however, if an
+ * error occurs, no further `tasks` will be performed, and the results object
+ * will only contain partial results. Invoked with (err, results).
+ * @returns {Promise} a promise, if a callback is not passed
+ * @example
+ *
+ * //Using Callbacks
+ * async.auto({
+ *     get_data: function(callback) {
+ *         // async code to get some data
+ *         callback(null, 'data', 'converted to array');
+ *     },
+ *     make_folder: function(callback) {
+ *         // async code to create a directory to store a file in
+ *         // this is run at the same time as getting the data
+ *         callback(null, 'folder');
+ *     },
+ *     write_file: ['get_data', 'make_folder', function(results, callback) {
+ *         // once there is some data and the directory exists,
+ *         // write the data to a file in the directory
+ *         callback(null, 'filename');
+ *     }],
+ *     email_link: ['write_file', function(results, callback) {
+ *         // once the file is written let's email a link to it...
+ *         callback(null, {'file':results.write_file, 'email':'user@example.com'});
+ *     }]
+ * }, function(err, results) {
+ *     if (err) {
+ *         console.log('err = ', err);
+ *     }
+ *     console.log('results = ', results);
+ *     // results = {
+ *     //     get_data: ['data', 'converted to array']
+ *     //     make_folder; 'folder',
+ *     //     write_file: 'filename'
+ *     //     email_link: { file: 'filename', email: 'user@example.com' }
+ *     // }
+ * });
+ *
+ * //Using Promises
+ * async.auto({
+ *     get_data: function(callback) {
+ *         console.log('in get_data');
+ *         // async code to get some data
+ *         callback(null, 'data', 'converted to array');
+ *     },
+ *     make_folder: function(callback) {
+ *         console.log('in make_folder');
+ *         // async code to create a directory to store a file in
+ *         // this is run at the same time as getting the data
+ *         callback(null, 'folder');
+ *     },
+ *     write_file: ['get_data', 'make_folder', function(results, callback) {
+ *         // once there is some data and the directory exists,
+ *         // write the data to a file in the directory
+ *         callback(null, 'filename');
+ *     }],
+ *     email_link: ['write_file', function(results, callback) {
+ *         // once the file is written let's email a link to it...
+ *         callback(null, {'file':results.write_file, 'email':'user@example.com'});
+ *     }]
+ * }).then(results => {
+ *     console.log('results = ', results);
+ *     // results = {
+ *     //     get_data: ['data', 'converted to array']
+ *     //     make_folder; 'folder',
+ *     //     write_file: 'filename'
+ *     //     email_link: { file: 'filename', email: 'user@example.com' }
+ *     // }
+ * }).catch(err => {
+ *     console.log('err = ', err);
+ * });
+ *
+ * //Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.auto({
+ *             get_data: function(callback) {
+ *                 // async code to get some data
+ *                 callback(null, 'data', 'converted to array');
+ *             },
+ *             make_folder: function(callback) {
+ *                 // async code to create a directory to store a file in
+ *                 // this is run at the same time as getting the data
+ *                 callback(null, 'folder');
+ *             },
+ *             write_file: ['get_data', 'make_folder', function(results, callback) {
+ *                 // once there is some data and the directory exists,
+ *                 // write the data to a file in the directory
+ *                 callback(null, 'filename');
+ *             }],
+ *             email_link: ['write_file', function(results, callback) {
+ *                 // once the file is written let's email a link to it...
+ *                 callback(null, {'file':results.write_file, 'email':'user@example.com'});
+ *             }]
+ *         });
+ *         console.log('results = ', results);
+ *         // results = {
+ *         //     get_data: ['data', 'converted to array']
+ *         //     make_folder; 'folder',
+ *         //     write_file: 'filename'
+ *         //     email_link: { file: 'filename', email: 'user@example.com' }
+ *         // }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function auto(tasks, concurrency, callback) {
+    if (typeof concurrency !== 'number') {
+        // concurrency is optional, shift the args.
+        callback = concurrency;
+        concurrency = null;
+    }
+    callback = once(callback || promiseCallback());
+    var numTasks = Object.keys(tasks).length;
+    if (!numTasks) {
+        return callback(null);
+    }
+    if (!concurrency) {
+        concurrency = numTasks;
+    }
+
+    var results = {};
+    var runningTasks = 0;
+    var canceled = false;
+    var hasError = false;
+
+    var listeners = Object.create(null);
+
+    var readyTasks = [];
+
+    // for cycle detection:
+    var readyToCheck = []; // tasks that have been identified as reachable
+    // without the possibility of returning to an ancestor task
+    var uncheckedDependencies = {};
+
+    Object.keys(tasks).forEach(key => {
+        var task = tasks[key];
+        if (!Array.isArray(task)) {
+            // no dependencies
+            enqueueTask(key, [task]);
+            readyToCheck.push(key);
+            return;
+        }
+
+        var dependencies = task.slice(0, task.length - 1);
+        var remainingDependencies = dependencies.length;
+        if (remainingDependencies === 0) {
+            enqueueTask(key, task);
+            readyToCheck.push(key);
+            return;
+        }
+        uncheckedDependencies[key] = remainingDependencies;
+
+        dependencies.forEach(dependencyName => {
+            if (!tasks[dependencyName]) {
+                throw new Error('async.auto task `' + key +
+                    '` has a non-existent dependency `' +
+                    dependencyName + '` in ' +
+                    dependencies.join(', '));
+            }
+            addListener(dependencyName, () => {
+                remainingDependencies--;
+                if (remainingDependencies === 0) {
+                    enqueueTask(key, task);
+                }
+            });
+        });
+    });
+
+    checkForDeadlocks();
+    processQueue();
+
+    function enqueueTask(key, task) {
+        readyTasks.push(() => runTask(key, task));
+    }
+
+    function processQueue() {
+        if (canceled) return
+        if (readyTasks.length === 0 && runningTasks === 0) {
+            return callback(null, results);
+        }
+        while(readyTasks.length && runningTasks < concurrency) {
+            var run = readyTasks.shift();
+            run();
+        }
+
+    }
+
+    function addListener(taskName, fn) {
+        var taskListeners = listeners[taskName];
+        if (!taskListeners) {
+            taskListeners = listeners[taskName] = [];
+        }
+
+        taskListeners.push(fn);
+    }
+
+    function taskComplete(taskName) {
+        var taskListeners = listeners[taskName] || [];
+        taskListeners.forEach(fn => fn());
+        processQueue();
+    }
+
+
+    function runTask(key, task) {
+        if (hasError) return;
+
+        var taskCallback = onlyOnce((err, ...result) => {
+            runningTasks--;
+            if (err === false) {
+                canceled = true;
+                return
+            }
+            if (result.length < 2) {
+                [result] = result;
+            }
+            if (err) {
+                var safeResults = {};
+                Object.keys(results).forEach(rkey => {
+                    safeResults[rkey] = results[rkey];
+                });
+                safeResults[key] = result;
+                hasError = true;
+                listeners = Object.create(null);
+                if (canceled) return
+                callback(err, safeResults);
+            } else {
+                results[key] = result;
+                taskComplete(key);
+            }
+        });
+
+        runningTasks++;
+        var taskFn = wrapAsync(task[task.length - 1]);
+        if (task.length > 1) {
+            taskFn(results, taskCallback);
+        } else {
+            taskFn(taskCallback);
+        }
+    }
+
+    function checkForDeadlocks() {
+        // Kahn's algorithm
+        // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
+        // http://connalle.blogspot.com/2013/10/topological-sortingkahn-algorithm.html
+        var currentTask;
+        var counter = 0;
+        while (readyToCheck.length) {
+            currentTask = readyToCheck.pop();
+            counter++;
+            getDependents(currentTask).forEach(dependent => {
+                if (--uncheckedDependencies[dependent] === 0) {
+                    readyToCheck.push(dependent);
+                }
+            });
+        }
+
+        if (counter !== numTasks) {
+            throw new Error(
+                'async.auto cannot execute tasks due to a recursive dependency'
+            );
+        }
+    }
+
+    function getDependents(taskName) {
+        var result = [];
+        Object.keys(tasks).forEach(key => {
+            const task = tasks[key];
+            if (Array.isArray(task) && task.indexOf(taskName) >= 0) {
+                result.push(key);
+            }
+        });
+        return result;
+    }
+
+    return callback[PROMISE_SYMBOL]
+}
+
+var FN_ARGS = /^(?:async\s+)?(?:function)?\s*\w*\s*\(\s*([^)]+)\s*\)(?:\s*{)/;
+var ARROW_FN_ARGS = /^(?:async\s+)?\(?\s*([^)=]+)\s*\)?(?:\s*=>)/;
+var FN_ARG_SPLIT = /,/;
+var FN_ARG = /(=.+)?(\s*)$/;
+
+function stripComments(string) {
+    let stripped = '';
+    let index = 0;
+    let endBlockComment = string.indexOf('*/');
+    while (index < string.length) {
+        if (string[index] === '/' && string[index+1] === '/') {
+            // inline comment
+            let endIndex = string.indexOf('\n', index);
+            index = (endIndex === -1) ? string.length : endIndex;
+        } else if ((endBlockComment !== -1) && (string[index] === '/') && (string[index+1] === '*')) {
+            // block comment
+            let endIndex = string.indexOf('*/', index);
+            if (endIndex !== -1) {
+                index = endIndex + 2;
+                endBlockComment = string.indexOf('*/', index);
+            } else {
+                stripped += string[index];
+                index++;
+            }
+        } else {
+            stripped += string[index];
+            index++;
+        }
+    }
+    return stripped;
+}
+
+function parseParams(func) {
+    const src = stripComments(func.toString());
+    let match = src.match(FN_ARGS);
+    if (!match) {
+        match = src.match(ARROW_FN_ARGS);
+    }
+    if (!match) throw new Error('could not parse args in autoInject\nSource:\n' + src)
+    let [, args] = match;
+    return args
+        .replace(/\s/g, '')
+        .split(FN_ARG_SPLIT)
+        .map((arg) => arg.replace(FN_ARG, '').trim());
+}
+
+/**
+ * A dependency-injected version of the [async.auto]{@link module:ControlFlow.auto} function. Dependent
+ * tasks are specified as parameters to the function, after the usual callback
+ * parameter, with the parameter names matching the names of the tasks it
+ * depends on. This can provide even more readable task graphs which can be
+ * easier to maintain.
+ *
+ * If a final callback is specified, the task results are similarly injected,
+ * specified as named parameters after the initial error parameter.
+ *
+ * The autoInject function is purely syntactic sugar and its semantics are
+ * otherwise equivalent to [async.auto]{@link module:ControlFlow.auto}.
+ *
+ * @name autoInject
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.auto]{@link module:ControlFlow.auto}
+ * @category Control Flow
+ * @param {Object} tasks - An object, each of whose properties is an {@link AsyncFunction} of
+ * the form 'func([dependencies...], callback). The object's key of a property
+ * serves as the name of the task defined by that property, i.e. can be used
+ * when specifying requirements for other tasks.
+ * * The `callback` parameter is a `callback(err, result)` which must be called
+ *   when finished, passing an `error` (which can be `null`) and the result of
+ *   the function's execution. The remaining parameters name other tasks on
+ *   which the task is dependent, and the results from those tasks are the
+ *   arguments of those parameters.
+ * @param {Function} [callback] - An optional callback which is called when all
+ * the tasks have been completed. It receives the `err` argument if any `tasks`
+ * pass an error to their callback, and a `results` object with any completed
+ * task results, similar to `auto`.
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * //  The example from `auto` can be rewritten as follows:
+ * async.autoInject({
+ *     get_data: function(callback) {
+ *         // async code to get some data
+ *         callback(null, 'data', 'converted to array');
+ *     },
+ *     make_folder: function(callback) {
+ *         // async code to create a directory to store a file in
+ *         // this is run at the same time as getting the data
+ *         callback(null, 'folder');
+ *     },
+ *     write_file: function(get_data, make_folder, callback) {
+ *         // once there is some data and the directory exists,
+ *         // write the data to a file in the directory
+ *         callback(null, 'filename');
+ *     },
+ *     email_link: function(write_file, callback) {
+ *         // once the file is written let's email a link to it...
+ *         // write_file contains the filename returned by write_file.
+ *         callback(null, {'file':write_file, 'email':'user@example.com'});
+ *     }
+ * }, function(err, results) {
+ *     console.log('err = ', err);
+ *     console.log('email_link = ', results.email_link);
+ * });
+ *
+ * // If you are using a JS minifier that mangles parameter names, `autoInject`
+ * // will not work with plain functions, since the parameter names will be
+ * // collapsed to a single letter identifier.  To work around this, you can
+ * // explicitly specify the names of the parameters your task function needs
+ * // in an array, similar to Angular.js dependency injection.
+ *
+ * // This still has an advantage over plain `auto`, since the results a task
+ * // depends on are still spread into arguments.
+ * async.autoInject({
+ *     //...
+ *     write_file: ['get_data', 'make_folder', function(get_data, make_folder, callback) {
+ *         callback(null, 'filename');
+ *     }],
+ *     email_link: ['write_file', function(write_file, callback) {
+ *         callback(null, {'file':write_file, 'email':'user@example.com'});
+ *     }]
+ *     //...
+ * }, function(err, results) {
+ *     console.log('err = ', err);
+ *     console.log('email_link = ', results.email_link);
+ * });
+ */
+function autoInject(tasks, callback) {
+    var newTasks = {};
+
+    Object.keys(tasks).forEach(key => {
+        var taskFn = tasks[key];
+        var params;
+        var fnIsAsync = isAsync(taskFn);
+        var hasNoDeps =
+            (!fnIsAsync && taskFn.length === 1) ||
+            (fnIsAsync && taskFn.length === 0);
+
+        if (Array.isArray(taskFn)) {
+            params = [...taskFn];
+            taskFn = params.pop();
+
+            newTasks[key] = params.concat(params.length > 0 ? newTask : taskFn);
+        } else if (hasNoDeps) {
+            // no dependencies, use the function as-is
+            newTasks[key] = taskFn;
+        } else {
+            params = parseParams(taskFn);
+            if ((taskFn.length === 0 && !fnIsAsync) && params.length === 0) {
+                throw new Error("autoInject task functions require explicit parameters.");
+            }
+
+            // remove callback param
+            if (!fnIsAsync) params.pop();
+
+            newTasks[key] = params.concat(newTask);
+        }
+
+        function newTask(results, taskCb) {
+            var newArgs = params.map(name => results[name]);
+            newArgs.push(taskCb);
+            wrapAsync(taskFn)(...newArgs);
+        }
+    });
+
+    return auto(newTasks, callback);
+}
+
+// Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation
+// used for queues. This implementation assumes that the node provided by the user can be modified
+// to adjust the next and last properties. We implement only the minimal functionality
+// for queue support.
+class DLL {
+    constructor() {
+        this.head = this.tail = null;
+        this.length = 0;
+    }
+
+    removeLink(node) {
+        if (node.prev) node.prev.next = node.next;
+        else this.head = node.next;
+        if (node.next) node.next.prev = node.prev;
+        else this.tail = node.prev;
+
+        node.prev = node.next = null;
+        this.length -= 1;
+        return node;
+    }
+
+    empty () {
+        while(this.head) this.shift();
+        return this;
+    }
+
+    insertAfter(node, newNode) {
+        newNode.prev = node;
+        newNode.next = node.next;
+        if (node.next) node.next.prev = newNode;
+        else this.tail = newNode;
+        node.next = newNode;
+        this.length += 1;
+    }
+
+    insertBefore(node, newNode) {
+        newNode.prev = node.prev;
+        newNode.next = node;
+        if (node.prev) node.prev.next = newNode;
+        else this.head = newNode;
+        node.prev = newNode;
+        this.length += 1;
+    }
+
+    unshift(node) {
+        if (this.head) this.insertBefore(this.head, node);
+        else setInitial(this, node);
+    }
+
+    push(node) {
+        if (this.tail) this.insertAfter(this.tail, node);
+        else setInitial(this, node);
+    }
+
+    shift() {
+        return this.head && this.removeLink(this.head);
+    }
+
+    pop() {
+        return this.tail && this.removeLink(this.tail);
+    }
+
+    toArray() {
+        return [...this]
+    }
+
+    *[Symbol.iterator] () {
+        var cur = this.head;
+        while (cur) {
+            yield cur.data;
+            cur = cur.next;
+        }
+    }
+
+    remove (testFn) {
+        var curr = this.head;
+        while(curr) {
+            var {next} = curr;
+            if (testFn(curr)) {
+                this.removeLink(curr);
+            }
+            curr = next;
+        }
+        return this;
+    }
+}
+
+function setInitial(dll, node) {
+    dll.length = 1;
+    dll.head = dll.tail = node;
+}
+
+function queue(worker, concurrency, payload) {
+    if (concurrency == null) {
+        concurrency = 1;
+    }
+    else if(concurrency === 0) {
+        throw new RangeError('Concurrency must not be zero');
+    }
+
+    var _worker = wrapAsync(worker);
+    var numRunning = 0;
+    var workersList = [];
+    const events = {
+        error: [],
+        drain: [],
+        saturated: [],
+        unsaturated: [],
+        empty: []
+    };
+
+    function on (event, handler) {
+        events[event].push(handler);
+    }
+
+    function once (event, handler) {
+        const handleAndRemove = (...args) => {
+            off(event, handleAndRemove);
+            handler(...args);
+        };
+        events[event].push(handleAndRemove);
+    }
+
+    function off (event, handler) {
+        if (!event) return Object.keys(events).forEach(ev => events[ev] = [])
+        if (!handler) return events[event] = []
+        events[event] = events[event].filter(ev => ev !== handler);
+    }
+
+    function trigger (event, ...args) {
+        events[event].forEach(handler => handler(...args));
+    }
+
+    var processingScheduled = false;
+    function _insert(data, insertAtFront, rejectOnError, callback) {
+        if (callback != null && typeof callback !== 'function') {
+            throw new Error('task callback must be a function');
+        }
+        q.started = true;
+
+        var res, rej;
+        function promiseCallback (err, ...args) {
+            // we don't care about the error, let the global error handler
+            // deal with it
+            if (err) return rejectOnError ? rej(err) : res()
+            if (args.length <= 1) return res(args[0])
+            res(args);
+        }
+
+        var item = q._createTaskItem(
+            data,
+            rejectOnError ? promiseCallback :
+                (callback || promiseCallback)
+        );
+
+        if (insertAtFront) {
+            q._tasks.unshift(item);
+        } else {
+            q._tasks.push(item);
+        }
+
+        if (!processingScheduled) {
+            processingScheduled = true;
+            setImmediate$1(() => {
+                processingScheduled = false;
+                q.process();
+            });
+        }
+
+        if (rejectOnError || !callback) {
+            return new Promise((resolve, reject) => {
+                res = resolve;
+                rej = reject;
+            })
+        }
+    }
+
+    function _createCB(tasks) {
+        return function (err, ...args) {
+            numRunning -= 1;
+
+            for (var i = 0, l = tasks.length; i < l; i++) {
+                var task = tasks[i];
+
+                var index = workersList.indexOf(task);
+                if (index === 0) {
+                    workersList.shift();
+                } else if (index > 0) {
+                    workersList.splice(index, 1);
+                }
+
+                task.callback(err, ...args);
+
+                if (err != null) {
+                    trigger('error', err, task.data);
+                }
+            }
+
+            if (numRunning <= (q.concurrency - q.buffer) ) {
+                trigger('unsaturated');
+            }
+
+            if (q.idle()) {
+                trigger('drain');
+            }
+            q.process();
+        };
+    }
+
+    function _maybeDrain(data) {
+        if (data.length === 0 && q.idle()) {
+            // call drain immediately if there are no tasks
+            setImmediate$1(() => trigger('drain'));
+            return true
+        }
+        return false
+    }
+
+    const eventMethod = (name) => (handler) => {
+        if (!handler) {
+            return new Promise((resolve, reject) => {
+                once(name, (err, data) => {
+                    if (err) return reject(err)
+                    resolve(data);
+                });
+            })
+        }
+        off(name);
+        on(name, handler);
+
+    };
+
+    var isProcessing = false;
+    var q = {
+        _tasks: new DLL(),
+        _createTaskItem (data, callback) {
+            return {
+                data,
+                callback
+            };
+        },
+        *[Symbol.iterator] () {
+            yield* q._tasks[Symbol.iterator]();
+        },
+        concurrency,
+        payload,
+        buffer: concurrency / 4,
+        started: false,
+        paused: false,
+        push (data, callback) {
+            if (Array.isArray(data)) {
+                if (_maybeDrain(data)) return
+                return data.map(datum => _insert(datum, false, false, callback))
+            }
+            return _insert(data, false, false, callback);
+        },
+        pushAsync (data, callback) {
+            if (Array.isArray(data)) {
+                if (_maybeDrain(data)) return
+                return data.map(datum => _insert(datum, false, true, callback))
+            }
+            return _insert(data, false, true, callback);
+        },
+        kill () {
+            off();
+            q._tasks.empty();
+        },
+        unshift (data, callback) {
+            if (Array.isArray(data)) {
+                if (_maybeDrain(data)) return
+                return data.map(datum => _insert(datum, true, false, callback))
+            }
+            return _insert(data, true, false, callback);
+        },
+        unshiftAsync (data, callback) {
+            if (Array.isArray(data)) {
+                if (_maybeDrain(data)) return
+                return data.map(datum => _insert(datum, true, true, callback))
+            }
+            return _insert(data, true, true, callback);
+        },
+        remove (testFn) {
+            q._tasks.remove(testFn);
+        },
+        process () {
+            // Avoid trying to start too many processing operations. This can occur
+            // when callbacks resolve synchronously (#1267).
+            if (isProcessing) {
+                return;
+            }
+            isProcessing = true;
+            while(!q.paused && numRunning < q.concurrency && q._tasks.length){
+                var tasks = [], data = [];
+                var l = q._tasks.length;
+                if (q.payload) l = Math.min(l, q.payload);
+                for (var i = 0; i < l; i++) {
+                    var node = q._tasks.shift();
+                    tasks.push(node);
+                    workersList.push(node);
+                    data.push(node.data);
+                }
+
+                numRunning += 1;
+
+                if (q._tasks.length === 0) {
+                    trigger('empty');
+                }
+
+                if (numRunning === q.concurrency) {
+                    trigger('saturated');
+                }
+
+                var cb = onlyOnce(_createCB(tasks));
+                _worker(data, cb);
+            }
+            isProcessing = false;
+        },
+        length () {
+            return q._tasks.length;
+        },
+        running () {
+            return numRunning;
+        },
+        workersList () {
+            return workersList;
+        },
+        idle() {
+            return q._tasks.length + numRunning === 0;
+        },
+        pause () {
+            q.paused = true;
+        },
+        resume () {
+            if (q.paused === false) { return; }
+            q.paused = false;
+            setImmediate$1(q.process);
+        }
+    };
+    // define these as fixed properties, so people get useful errors when updating
+    Object.defineProperties(q, {
+        saturated: {
+            writable: false,
+            value: eventMethod('saturated')
+        },
+        unsaturated: {
+            writable: false,
+            value: eventMethod('unsaturated')
+        },
+        empty: {
+            writable: false,
+            value: eventMethod('empty')
+        },
+        drain: {
+            writable: false,
+            value: eventMethod('drain')
+        },
+        error: {
+            writable: false,
+            value: eventMethod('error')
+        },
+    });
+    return q;
+}
+
+/**
+ * Creates a `cargo` object with the specified payload. Tasks added to the
+ * cargo will be processed altogether (up to the `payload` limit). If the
+ * `worker` is in progress, the task is queued until it becomes available. Once
+ * the `worker` has completed some tasks, each callback of those tasks is
+ * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966)
+ * for how `cargo` and `queue` work.
+ *
+ * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers
+ * at a time, cargo passes an array of tasks to a single worker, repeating
+ * when the worker is finished.
+ *
+ * @name cargo
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.queue]{@link module:ControlFlow.queue}
+ * @category Control Flow
+ * @param {AsyncFunction} worker - An asynchronous function for processing an array
+ * of queued tasks. Invoked with `(tasks, callback)`.
+ * @param {number} [payload=Infinity] - An optional `integer` for determining
+ * how many tasks should be processed per round; if omitted, the default is
+ * unlimited.
+ * @returns {module:ControlFlow.QueueObject} A cargo object to manage the tasks. Callbacks can
+ * attached as certain properties to listen for specific events during the
+ * lifecycle of the cargo and inner queue.
+ * @example
+ *
+ * // create a cargo object with payload 2
+ * var cargo = async.cargo(function(tasks, callback) {
+ *     for (var i=0; i<tasks.length; i++) {
+ *         console.log('hello ' + tasks[i].name);
+ *     }
+ *     callback();
+ * }, 2);
+ *
+ * // add some items
+ * cargo.push({name: 'foo'}, function(err) {
+ *     console.log('finished processing foo');
+ * });
+ * cargo.push({name: 'bar'}, function(err) {
+ *     console.log('finished processing bar');
+ * });
+ * await cargo.push({name: 'baz'});
+ * console.log('finished processing baz');
+ */
+function cargo(worker, payload) {
+    return queue(worker, 1, payload);
+}
+
+/**
+ * Creates a `cargoQueue` object with the specified payload. Tasks added to the
+ * cargoQueue will be processed together (up to the `payload` limit) in `concurrency` parallel workers.
+ * If the all `workers` are in progress, the task is queued until one becomes available. Once
+ * a `worker` has completed some tasks, each callback of those tasks is
+ * called. Check out [these](https://camo.githubusercontent.com/6bbd36f4cf5b35a0f11a96dcd2e97711ffc2fb37/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130382f62626330636662302d356632392d313165322d393734662d3333393763363464633835382e676966) [animations](https://camo.githubusercontent.com/f4810e00e1c5f5f8addbe3e9f49064fd5d102699/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313637363837312f36383130312f38346339323036362d356632392d313165322d383134662d3964336430323431336266642e676966)
+ * for how `cargo` and `queue` work.
+ *
+ * While [`queue`]{@link module:ControlFlow.queue} passes only one task to one of a group of workers
+ * at a time, and [`cargo`]{@link module:ControlFlow.cargo} passes an array of tasks to a single worker,
+ * the cargoQueue passes an array of tasks to multiple parallel workers.
+ *
+ * @name cargoQueue
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.queue]{@link module:ControlFlow.queue}
+ * @see [async.cargo]{@link module:ControlFLow.cargo}
+ * @category Control Flow
+ * @param {AsyncFunction} worker - An asynchronous function for processing an array
+ * of queued tasks. Invoked with `(tasks, callback)`.
+ * @param {number} [concurrency=1] - An `integer` for determining how many
+ * `worker` functions should be run in parallel.  If omitted, the concurrency
+ * defaults to `1`.  If the concurrency is `0`, an error is thrown.
+ * @param {number} [payload=Infinity] - An optional `integer` for determining
+ * how many tasks should be processed per round; if omitted, the default is
+ * unlimited.
+ * @returns {module:ControlFlow.QueueObject} A cargoQueue object to manage the tasks. Callbacks can
+ * attached as certain properties to listen for specific events during the
+ * lifecycle of the cargoQueue and inner queue.
+ * @example
+ *
+ * // create a cargoQueue object with payload 2 and concurrency 2
+ * var cargoQueue = async.cargoQueue(function(tasks, callback) {
+ *     for (var i=0; i<tasks.length; i++) {
+ *         console.log('hello ' + tasks[i].name);
+ *     }
+ *     callback();
+ * }, 2, 2);
+ *
+ * // add some items
+ * cargoQueue.push({name: 'foo'}, function(err) {
+ *     console.log('finished processing foo');
+ * });
+ * cargoQueue.push({name: 'bar'}, function(err) {
+ *     console.log('finished processing bar');
+ * });
+ * cargoQueue.push({name: 'baz'}, function(err) {
+ *     console.log('finished processing baz');
+ * });
+ * cargoQueue.push({name: 'boo'}, function(err) {
+ *     console.log('finished processing boo');
+ * });
+ */
+function cargo$1(worker, concurrency, payload) {
+    return queue(worker, concurrency, payload);
+}
+
+/**
+ * Reduces `coll` into a single value using an async `iteratee` to return each
+ * successive step. `memo` is the initial state of the reduction. This function
+ * only operates in series.
+ *
+ * For performance reasons, it may make sense to split a call to this function
+ * into a parallel map, and then use the normal `Array.prototype.reduce` on the
+ * results. This function is for situations where each step in the reduction
+ * needs to be async; if you can get the data before reducing it, then it's
+ * probably a good idea to do so.
+ *
+ * @name reduce
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias inject
+ * @alias foldl
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {*} memo - The initial state of the reduction.
+ * @param {AsyncFunction} iteratee - A function applied to each item in the
+ * array to produce the next step in the reduction.
+ * The `iteratee` should complete with the next state of the reduction.
+ * If the iteratee completes with an error, the reduction is stopped and the
+ * main `callback` is immediately called with the error.
+ * Invoked with (memo, item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result is the reduced value. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ * // file4.txt does not exist
+ *
+ * const fileList = ['file1.txt','file2.txt','file3.txt'];
+ * const withMissingFileList = ['file1.txt','file2.txt','file3.txt', 'file4.txt'];
+ *
+ * // asynchronous function that computes the file size in bytes
+ * // file size is added to the memoized value, then returned
+ * function getFileSizeInBytes(memo, file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, memo + stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.reduce(fileList, 0, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // 6000
+ *         // which is the sum of the file sizes of the three files
+ *     }
+ * });
+ *
+ * // Error Handling
+ * async.reduce(withMissingFileList, 0, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     } else {
+ *         console.log(result);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.reduce(fileList, 0, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ *     // 6000
+ *     // which is the sum of the file sizes of the three files
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.reduce(withMissingFileList, 0, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.reduce(fileList, 0, getFileSizeInBytes);
+ *         console.log(result);
+ *         // 6000
+ *         // which is the sum of the file sizes of the three files
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes);
+ *         console.log(result);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function reduce(coll, memo, iteratee, callback) {
+    callback = once(callback);
+    var _iteratee = wrapAsync(iteratee);
+    return eachOfSeries$1(coll, (x, i, iterCb) => {
+        _iteratee(memo, x, (err, v) => {
+            memo = v;
+            iterCb(err);
+        });
+    }, err => callback(err, memo));
+}
+var reduce$1 = awaitify(reduce, 4);
+
+/**
+ * Version of the compose function that is more natural to read. Each function
+ * consumes the return value of the previous function. It is the equivalent of
+ * [compose]{@link module:ControlFlow.compose} with the arguments reversed.
+ *
+ * Each function is executed with the `this` binding of the composed function.
+ *
+ * @name seq
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.compose]{@link module:ControlFlow.compose}
+ * @category Control Flow
+ * @param {...AsyncFunction} functions - the asynchronous functions to compose
+ * @returns {Function} a function that composes the `functions` in order
+ * @example
+ *
+ * // Requires lodash (or underscore), express3 and dresende's orm2.
+ * // Part of an app, that fetches cats of the logged user.
+ * // This example uses `seq` function to avoid overnesting and error
+ * // handling clutter.
+ * app.get('/cats', function(request, response) {
+ *     var User = request.models.User;
+ *     async.seq(
+ *         User.get.bind(User),  // 'User.get' has signature (id, callback(err, data))
+ *         function(user, fn) {
+ *             user.getCats(fn);      // 'getCats' has signature (callback(err, data))
+ *         }
+ *     )(req.session.user_id, function (err, cats) {
+ *         if (err) {
+ *             console.error(err);
+ *             response.json({ status: 'error', message: err.message });
+ *         } else {
+ *             response.json({ status: 'ok', message: 'Cats found', data: cats });
+ *         }
+ *     });
+ * });
+ */
+function seq(...functions) {
+    var _functions = functions.map(wrapAsync);
+    return function (...args) {
+        var that = this;
+
+        var cb = args[args.length - 1];
+        if (typeof cb == 'function') {
+            args.pop();
+        } else {
+            cb = promiseCallback();
+        }
+
+        reduce$1(_functions, args, (newargs, fn, iterCb) => {
+            fn.apply(that, newargs.concat((err, ...nextargs) => {
+                iterCb(err, nextargs);
+            }));
+        },
+        (err, results) => cb(err, ...results));
+
+        return cb[PROMISE_SYMBOL]
+    };
+}
+
+/**
+ * Creates a function which is a composition of the passed asynchronous
+ * functions. Each function consumes the return value of the function that
+ * follows. Composing functions `f()`, `g()`, and `h()` would produce the result
+ * of `f(g(h()))`, only this version uses callbacks to obtain the return values.
+ *
+ * If the last argument to the composed function is not a function, a promise
+ * is returned when you call it.
+ *
+ * Each function is executed with the `this` binding of the composed function.
+ *
+ * @name compose
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {...AsyncFunction} functions - the asynchronous functions to compose
+ * @returns {Function} an asynchronous function that is the composed
+ * asynchronous `functions`
+ * @example
+ *
+ * function add1(n, callback) {
+ *     setTimeout(function () {
+ *         callback(null, n + 1);
+ *     }, 10);
+ * }
+ *
+ * function mul3(n, callback) {
+ *     setTimeout(function () {
+ *         callback(null, n * 3);
+ *     }, 10);
+ * }
+ *
+ * var add1mul3 = async.compose(mul3, add1);
+ * add1mul3(4, function (err, result) {
+ *     // result now equals 15
+ * });
+ */
+function compose(...args) {
+    return seq(...args.reverse());
+}
+
+/**
+ * The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name mapLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.map]{@link module:Collections.map}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with the transformed item.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Results is an array of the
+ * transformed items from the `coll`. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function mapLimit (coll, limit, iteratee, callback) {
+    return _asyncMap(eachOfLimit(limit), coll, iteratee, callback)
+}
+var mapLimit$1 = awaitify(mapLimit, 4);
+
+/**
+ * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name concatLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.concat]{@link module:Collections.concat}
+ * @category Collection
+ * @alias flatMapLimit
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
+ * which should use an array as its result. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is an array
+ * containing the concatenated results of the `iteratee` function. Invoked with
+ * (err, results).
+ * @returns A Promise, if no callback is passed
+ */
+function concatLimit(coll, limit, iteratee, callback) {
+    var _iteratee = wrapAsync(iteratee);
+    return mapLimit$1(coll, limit, (val, iterCb) => {
+        _iteratee(val, (err, ...args) => {
+            if (err) return iterCb(err);
+            return iterCb(err, args);
+        });
+    }, (err, mapResults) => {
+        var result = [];
+        for (var i = 0; i < mapResults.length; i++) {
+            if (mapResults[i]) {
+                result = result.concat(...mapResults[i]);
+            }
+        }
+
+        return callback(err, result);
+    });
+}
+var concatLimit$1 = awaitify(concatLimit, 4);
+
+/**
+ * Applies `iteratee` to each item in `coll`, concatenating the results. Returns
+ * the concatenated list. The `iteratee`s are called in parallel, and the
+ * results are concatenated as they return. The results array will be returned in
+ * the original order of `coll` passed to the `iteratee` function.
+ *
+ * @name concat
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @alias flatMap
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
+ * which should use an array as its result. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is an array
+ * containing the concatenated results of the `iteratee` function. Invoked with
+ * (err, results).
+ * @returns A Promise, if no callback is passed
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * let directoryList = ['dir1','dir2','dir3'];
+ * let withMissingDirectoryList = ['dir1','dir2','dir3', 'dir4'];
+ *
+ * // Using callbacks
+ * async.concat(directoryList, fs.readdir, function(err, results) {
+ *    if (err) {
+ *        console.log(err);
+ *    } else {
+ *        console.log(results);
+ *        // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+ *    }
+ * });
+ *
+ * // Error Handling
+ * async.concat(withMissingDirectoryList, fs.readdir, function(err, results) {
+ *    if (err) {
+ *        console.log(err);
+ *        // [ Error: ENOENT: no such file or directory ]
+ *        // since dir4 does not exist
+ *    } else {
+ *        console.log(results);
+ *    }
+ * });
+ *
+ * // Using Promises
+ * async.concat(directoryList, fs.readdir)
+ * .then(results => {
+ *     console.log(results);
+ *     // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+ * }).catch(err => {
+ *      console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.concat(withMissingDirectoryList, fs.readdir)
+ * .then(results => {
+ *     console.log(results);
+ * }).catch(err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ *     // since dir4 does not exist
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.concat(directoryList, fs.readdir);
+ *         console.log(results);
+ *         // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+ *     } catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let results = await async.concat(withMissingDirectoryList, fs.readdir);
+ *         console.log(results);
+ *     } catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *         // since dir4 does not exist
+ *     }
+ * }
+ *
+ */
+function concat(coll, iteratee, callback) {
+    return concatLimit$1(coll, Infinity, iteratee, callback)
+}
+var concat$1 = awaitify(concat, 3);
+
+/**
+ * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time.
+ *
+ * @name concatSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.concat]{@link module:Collections.concat}
+ * @category Collection
+ * @alias flatMapSeries
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`.
+ * The iteratee should complete with an array an array of results.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is an array
+ * containing the concatenated results of the `iteratee` function. Invoked with
+ * (err, results).
+ * @returns A Promise, if no callback is passed
+ */
+function concatSeries(coll, iteratee, callback) {
+    return concatLimit$1(coll, 1, iteratee, callback)
+}
+var concatSeries$1 = awaitify(concatSeries, 3);
+
+/**
+ * Returns a function that when called, calls-back with the values provided.
+ * Useful as the first function in a [`waterfall`]{@link module:ControlFlow.waterfall}, or for plugging values in to
+ * [`auto`]{@link module:ControlFlow.auto}.
+ *
+ * @name constant
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {...*} arguments... - Any number of arguments to automatically invoke
+ * callback with.
+ * @returns {AsyncFunction} Returns a function that when invoked, automatically
+ * invokes the callback with the previous given arguments.
+ * @example
+ *
+ * async.waterfall([
+ *     async.constant(42),
+ *     function (value, next) {
+ *         // value === 42
+ *     },
+ *     //...
+ * ], callback);
+ *
+ * async.waterfall([
+ *     async.constant(filename, "utf8"),
+ *     fs.readFile,
+ *     function (fileData, next) {
+ *         //...
+ *     }
+ *     //...
+ * ], callback);
+ *
+ * async.auto({
+ *     hostname: async.constant("https://server.net/"),
+ *     port: findFreePort,
+ *     launchServer: ["hostname", "port", function (options, cb) {
+ *         startServer(options, cb);
+ *     }],
+ *     //...
+ * }, callback);
+ */
+function constant(...args) {
+    return function (...ignoredArgs/*, callback*/) {
+        var callback = ignoredArgs.pop();
+        return callback(null, ...args);
+    };
+}
+
+function _createTester(check, getResult) {
+    return (eachfn, arr, _iteratee, cb) => {
+        var testPassed = false;
+        var testResult;
+        const iteratee = wrapAsync(_iteratee);
+        eachfn(arr, (value, _, callback) => {
+            iteratee(value, (err, result) => {
+                if (err || err === false) return callback(err);
+
+                if (check(result) && !testResult) {
+                    testPassed = true;
+                    testResult = getResult(true, value);
+                    return callback(null, breakLoop);
+                }
+                callback();
+            });
+        }, err => {
+            if (err) return cb(err);
+            cb(null, testPassed ? testResult : getResult(false));
+        });
+    };
+}
+
+/**
+ * Returns the first value in `coll` that passes an async truth test. The
+ * `iteratee` is applied in parallel, meaning the first iteratee to return
+ * `true` will fire the detect `callback` with that result. That means the
+ * result might not be the first item in the original `coll` (in terms of order)
+ * that passes the test.
+
+ * If order within the original `coll` is important, then look at
+ * [`detectSeries`]{@link module:Collections.detectSeries}.
+ *
+ * @name detect
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias find
+ * @category Collections
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+ * The iteratee must complete with a boolean value as its result.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the `iteratee` functions have finished.
+ * Result will be the first item in the array that passes the truth test
+ * (iteratee) or the value `undefined` if none passed. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists,
+ *    function(err, result) {
+ *        console.log(result);
+ *        // dir1/file1.txt
+ *        // result now equals the first file in the list that exists
+ *    }
+ *);
+ *
+ * // Using Promises
+ * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists)
+ * .then(result => {
+ *     console.log(result);
+ *     // dir1/file1.txt
+ *     // result now equals the first file in the list that exists
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists);
+ *         console.log(result);
+ *         // dir1/file1.txt
+ *         // result now equals the file in the list that exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function detect(coll, iteratee, callback) {
+    return _createTester(bool => bool, (res, item) => item)(eachOf$1, coll, iteratee, callback)
+}
+var detect$1 = awaitify(detect, 3);
+
+/**
+ * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name detectLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.detect]{@link module:Collections.detect}
+ * @alias findLimit
+ * @category Collections
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+ * The iteratee must complete with a boolean value as its result.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the `iteratee` functions have finished.
+ * Result will be the first item in the array that passes the truth test
+ * (iteratee) or the value `undefined` if none passed. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function detectLimit(coll, limit, iteratee, callback) {
+    return _createTester(bool => bool, (res, item) => item)(eachOfLimit(limit), coll, iteratee, callback)
+}
+var detectLimit$1 = awaitify(detectLimit, 4);
+
+/**
+ * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time.
+ *
+ * @name detectSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.detect]{@link module:Collections.detect}
+ * @alias findSeries
+ * @category Collections
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+ * The iteratee must complete with a boolean value as its result.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the `iteratee` functions have finished.
+ * Result will be the first item in the array that passes the truth test
+ * (iteratee) or the value `undefined` if none passed. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function detectSeries(coll, iteratee, callback) {
+    return _createTester(bool => bool, (res, item) => item)(eachOfLimit(1), coll, iteratee, callback)
+}
+
+var detectSeries$1 = awaitify(detectSeries, 3);
+
+function consoleFunc(name) {
+    return (fn, ...args) => wrapAsync(fn)(...args, (err, ...resultArgs) => {
+        /* istanbul ignore else */
+        if (typeof console === 'object') {
+            /* istanbul ignore else */
+            if (err) {
+                /* istanbul ignore else */
+                if (console.error) {
+                    console.error(err);
+                }
+            } else if (console[name]) { /* istanbul ignore else */
+                resultArgs.forEach(x => console[name](x));
+            }
+        }
+    })
+}
+
+/**
+ * Logs the result of an [`async` function]{@link AsyncFunction} to the
+ * `console` using `console.dir` to display the properties of the resulting object.
+ * Only works in Node.js or in browsers that support `console.dir` and
+ * `console.error` (such as FF and Chrome).
+ * If multiple arguments are returned from the async function,
+ * `console.dir` is called on each argument in order.
+ *
+ * @name dir
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} function - The function you want to eventually apply
+ * all arguments to.
+ * @param {...*} arguments... - Any number of arguments to apply to the function.
+ * @example
+ *
+ * // in a module
+ * var hello = function(name, callback) {
+ *     setTimeout(function() {
+ *         callback(null, {hello: name});
+ *     }, 1000);
+ * };
+ *
+ * // in the node repl
+ * node> async.dir(hello, 'world');
+ * {hello: 'world'}
+ */
+var dir = consoleFunc('dir');
+
+/**
+ * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in
+ * the order of operations, the arguments `test` and `iteratee` are switched.
+ *
+ * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
+ *
+ * @name doWhilst
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.whilst]{@link module:ControlFlow.whilst}
+ * @category Control Flow
+ * @param {AsyncFunction} iteratee - A function which is called each time `test`
+ * passes. Invoked with (callback).
+ * @param {AsyncFunction} test - asynchronous truth test to perform after each
+ * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the
+ * non-error args from the previous callback of `iteratee`.
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has failed and repeated execution of `iteratee` has stopped.
+ * `callback` will be passed an error and any arguments passed to the final
+ * `iteratee`'s callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function doWhilst(iteratee, test, callback) {
+    callback = onlyOnce(callback);
+    var _fn = wrapAsync(iteratee);
+    var _test = wrapAsync(test);
+    var results;
+
+    function next(err, ...args) {
+        if (err) return callback(err);
+        if (err === false) return;
+        results = args;
+        _test(...args, check);
+    }
+
+    function check(err, truth) {
+        if (err) return callback(err);
+        if (err === false) return;
+        if (!truth) return callback(null, ...results);
+        _fn(next);
+    }
+
+    return check(null, true);
+}
+
+var doWhilst$1 = awaitify(doWhilst, 3);
+
+/**
+ * Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the
+ * argument ordering differs from `until`.
+ *
+ * @name doUntil
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.doWhilst]{@link module:ControlFlow.doWhilst}
+ * @category Control Flow
+ * @param {AsyncFunction} iteratee - An async function which is called each time
+ * `test` fails. Invoked with (callback).
+ * @param {AsyncFunction} test - asynchronous truth test to perform after each
+ * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the
+ * non-error args from the previous callback of `iteratee`
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has passed and repeated execution of `iteratee` has stopped. `callback`
+ * will be passed an error and any arguments passed to the final `iteratee`'s
+ * callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function doUntil(iteratee, test, callback) {
+    const _test = wrapAsync(test);
+    return doWhilst$1(iteratee, (...args) => {
+        const cb = args.pop();
+        _test(...args, (err, truth) => cb (err, !truth));
+    }, callback);
+}
+
+function _withoutIndex(iteratee) {
+    return (value, index, callback) => iteratee(value, callback);
+}
+
+/**
+ * Applies the function `iteratee` to each item in `coll`, in parallel.
+ * The `iteratee` is called with an item from the list, and a callback for when
+ * it has finished. If the `iteratee` passes an error to its `callback`, the
+ * main `callback` (for the `each` function) is immediately called with the
+ * error.
+ *
+ * Note, that since this function applies `iteratee` to each item in parallel,
+ * there is no guarantee that the iteratee functions will complete in order.
+ *
+ * @name each
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias forEach
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to
+ * each item in `coll`. Invoked with (item, callback).
+ * The array index is not passed to the iteratee.
+ * If you need the index, use `eachOf`.
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * const fileList = [ 'dir1/file2.txt', 'dir2/file3.txt', 'dir/file5.txt'];
+ * const withMissingFileList = ['dir1/file1.txt', 'dir4/file2.txt'];
+ *
+ * // asynchronous function that deletes a file
+ * const deleteFile = function(file, callback) {
+ *     fs.unlink(file, callback);
+ * };
+ *
+ * // Using callbacks
+ * async.each(fileList, deleteFile, function(err) {
+ *     if( err ) {
+ *         console.log(err);
+ *     } else {
+ *         console.log('All files have been deleted successfully');
+ *     }
+ * });
+ *
+ * // Error Handling
+ * async.each(withMissingFileList, deleteFile, function(err){
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ *     // since dir4/file2.txt does not exist
+ *     // dir1/file1.txt could have been deleted
+ * });
+ *
+ * // Using Promises
+ * async.each(fileList, deleteFile)
+ * .then( () => {
+ *     console.log('All files have been deleted successfully');
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.each(fileList, deleteFile)
+ * .then( () => {
+ *     console.log('All files have been deleted successfully');
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ *     // since dir4/file2.txt does not exist
+ *     // dir1/file1.txt could have been deleted
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         await async.each(files, deleteFile);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         await async.each(withMissingFileList, deleteFile);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *         // since dir4/file2.txt does not exist
+ *         // dir1/file1.txt could have been deleted
+ *     }
+ * }
+ *
+ */
+function eachLimit(coll, iteratee, callback) {
+    return eachOf$1(coll, _withoutIndex(wrapAsync(iteratee)), callback);
+}
+
+var each = awaitify(eachLimit, 3);
+
+/**
+ * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name eachLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.each]{@link module:Collections.each}
+ * @alias forEachLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The array index is not passed to the iteratee.
+ * If you need the index, use `eachOfLimit`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachLimit$1(coll, limit, iteratee, callback) {
+    return eachOfLimit(limit)(coll, _withoutIndex(wrapAsync(iteratee)), callback);
+}
+var eachLimit$2 = awaitify(eachLimit$1, 4);
+
+/**
+ * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time.
+ *
+ * Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item
+ * in series and therefore the iteratee functions will complete in order.
+
+ * @name eachSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.each]{@link module:Collections.each}
+ * @alias forEachSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each
+ * item in `coll`.
+ * The array index is not passed to the iteratee.
+ * If you need the index, use `eachOfSeries`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachSeries(coll, iteratee, callback) {
+    return eachLimit$2(coll, 1, iteratee, callback)
+}
+var eachSeries$1 = awaitify(eachSeries, 3);
+
+/**
+ * Wrap an async function and ensure it calls its callback on a later tick of
+ * the event loop.  If the function already calls its callback on a next tick,
+ * no extra deferral is added. This is useful for preventing stack overflows
+ * (`RangeError: Maximum call stack size exceeded`) and generally keeping
+ * [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony)
+ * contained. ES2017 `async` functions are returned as-is -- they are immune
+ * to Zalgo's corrupting influences, as they always resolve on a later tick.
+ *
+ * @name ensureAsync
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} fn - an async function, one that expects a node-style
+ * callback as its last argument.
+ * @returns {AsyncFunction} Returns a wrapped function with the exact same call
+ * signature as the function passed in.
+ * @example
+ *
+ * function sometimesAsync(arg, callback) {
+ *     if (cache[arg]) {
+ *         return callback(null, cache[arg]); // this would be synchronous!!
+ *     } else {
+ *         doSomeIO(arg, callback); // this IO would be asynchronous
+ *     }
+ * }
+ *
+ * // this has a risk of stack overflows if many results are cached in a row
+ * async.mapSeries(args, sometimesAsync, done);
+ *
+ * // this will defer sometimesAsync's callback if necessary,
+ * // preventing stack overflows
+ * async.mapSeries(args, async.ensureAsync(sometimesAsync), done);
+ */
+function ensureAsync(fn) {
+    if (isAsync(fn)) return fn;
+    return function (...args/*, callback*/) {
+        var callback = args.pop();
+        var sync = true;
+        args.push((...innerArgs) => {
+            if (sync) {
+                setImmediate$1(() => callback(...innerArgs));
+            } else {
+                callback(...innerArgs);
+            }
+        });
+        fn.apply(this, args);
+        sync = false;
+    };
+}
+
+/**
+ * Returns `true` if every element in `coll` satisfies an async test. If any
+ * iteratee call returns `false`, the main `callback` is immediately called.
+ *
+ * @name every
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias all
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collection in parallel.
+ * The iteratee must complete with a boolean result value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result will be either `true` or `false`
+ * depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file5.txt'];
+ * const withMissingFileList = ['file1.txt','file2.txt','file4.txt'];
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.every(fileList, fileExists, function(err, result) {
+ *     console.log(result);
+ *     // true
+ *     // result is true since every file exists
+ * });
+ *
+ * async.every(withMissingFileList, fileExists, function(err, result) {
+ *     console.log(result);
+ *     // false
+ *     // result is false since NOT every file exists
+ * });
+ *
+ * // Using Promises
+ * async.every(fileList, fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // true
+ *     // result is true since every file exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * async.every(withMissingFileList, fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // false
+ *     // result is false since NOT every file exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.every(fileList, fileExists);
+ *         console.log(result);
+ *         // true
+ *         // result is true since every file exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * async () => {
+ *     try {
+ *         let result = await async.every(withMissingFileList, fileExists);
+ *         console.log(result);
+ *         // false
+ *         // result is false since NOT every file exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function every(coll, iteratee, callback) {
+    return _createTester(bool => !bool, res => !res)(eachOf$1, coll, iteratee, callback)
+}
+var every$1 = awaitify(every, 3);
+
+/**
+ * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name everyLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.every]{@link module:Collections.every}
+ * @alias allLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collection in parallel.
+ * The iteratee must complete with a boolean result value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result will be either `true` or `false`
+ * depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function everyLimit(coll, limit, iteratee, callback) {
+    return _createTester(bool => !bool, res => !res)(eachOfLimit(limit), coll, iteratee, callback)
+}
+var everyLimit$1 = awaitify(everyLimit, 4);
+
+/**
+ * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time.
+ *
+ * @name everySeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.every]{@link module:Collections.every}
+ * @alias allSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collection in series.
+ * The iteratee must complete with a boolean result value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result will be either `true` or `false`
+ * depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function everySeries(coll, iteratee, callback) {
+    return _createTester(bool => !bool, res => !res)(eachOfSeries$1, coll, iteratee, callback)
+}
+var everySeries$1 = awaitify(everySeries, 3);
+
+function filterArray(eachfn, arr, iteratee, callback) {
+    var truthValues = new Array(arr.length);
+    eachfn(arr, (x, index, iterCb) => {
+        iteratee(x, (err, v) => {
+            truthValues[index] = !!v;
+            iterCb(err);
+        });
+    }, err => {
+        if (err) return callback(err);
+        var results = [];
+        for (var i = 0; i < arr.length; i++) {
+            if (truthValues[i]) results.push(arr[i]);
+        }
+        callback(null, results);
+    });
+}
+
+function filterGeneric(eachfn, coll, iteratee, callback) {
+    var results = [];
+    eachfn(coll, (x, index, iterCb) => {
+        iteratee(x, (err, v) => {
+            if (err) return iterCb(err);
+            if (v) {
+                results.push({index, value: x});
+            }
+            iterCb(err);
+        });
+    }, err => {
+        if (err) return callback(err);
+        callback(null, results
+            .sort((a, b) => a.index - b.index)
+            .map(v => v.value));
+    });
+}
+
+function _filter(eachfn, coll, iteratee, callback) {
+    var filter = isArrayLike(coll) ? filterArray : filterGeneric;
+    return filter(eachfn, coll, wrapAsync(iteratee), callback);
+}
+
+/**
+ * Returns a new array of all the values in `coll` which pass an async truth
+ * test. This operation is performed in parallel, but the results array will be
+ * in the same order as the original.
+ *
+ * @name filter
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias select
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+ * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+ * with a boolean argument once it has completed. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ *
+ * const files = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt'];
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.filter(files, fileExists, function(err, results) {
+ *    if(err) {
+ *        console.log(err);
+ *    } else {
+ *        console.log(results);
+ *        // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+ *        // results is now an array of the existing files
+ *    }
+ * });
+ *
+ * // Using Promises
+ * async.filter(files, fileExists)
+ * .then(results => {
+ *     console.log(results);
+ *     // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+ *     // results is now an array of the existing files
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.filter(files, fileExists);
+ *         console.log(results);
+ *         // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+ *         // results is now an array of the existing files
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function filter (coll, iteratee, callback) {
+    return _filter(eachOf$1, coll, iteratee, callback)
+}
+var filter$1 = awaitify(filter, 3);
+
+/**
+ * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name filterLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.filter]{@link module:Collections.filter}
+ * @alias selectLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+ * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+ * with a boolean argument once it has completed. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function filterLimit (coll, limit, iteratee, callback) {
+    return _filter(eachOfLimit(limit), coll, iteratee, callback)
+}
+var filterLimit$1 = awaitify(filterLimit, 4);
+
+/**
+ * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time.
+ *
+ * @name filterSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.filter]{@link module:Collections.filter}
+ * @alias selectSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+ * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+ * with a boolean argument once it has completed. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results)
+ * @returns {Promise} a promise, if no callback provided
+ */
+function filterSeries (coll, iteratee, callback) {
+    return _filter(eachOfSeries$1, coll, iteratee, callback)
+}
+var filterSeries$1 = awaitify(filterSeries, 3);
+
+/**
+ * Calls the asynchronous function `fn` with a callback parameter that allows it
+ * to call itself again, in series, indefinitely.
+
+ * If an error is passed to the callback then `errback` is called with the
+ * error, and execution stops, otherwise it will never be called.
+ *
+ * @name forever
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {AsyncFunction} fn - an async function to call repeatedly.
+ * Invoked with (next).
+ * @param {Function} [errback] - when `fn` passes an error to it's callback,
+ * this function will be called, and execution stops. Invoked with (err).
+ * @returns {Promise} a promise that rejects if an error occurs and an errback
+ * is not passed
+ * @example
+ *
+ * async.forever(
+ *     function(next) {
+ *         // next is suitable for passing to things that need a callback(err [, whatever]);
+ *         // it will result in this function being called again.
+ *     },
+ *     function(err) {
+ *         // if next is called with a value in its first parameter, it will appear
+ *         // in here as 'err', and execution will stop.
+ *     }
+ * );
+ */
+function forever(fn, errback) {
+    var done = onlyOnce(errback);
+    var task = wrapAsync(ensureAsync(fn));
+
+    function next(err) {
+        if (err) return done(err);
+        if (err === false) return;
+        task(next);
+    }
+    return next();
+}
+var forever$1 = awaitify(forever, 2);
+
+/**
+ * The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name groupByLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.groupBy]{@link module:Collections.groupBy}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with a `key` to group the value under.
+ * Invoked with (value, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Result is an `Object` whoses
+ * properties are arrays of values which returned the corresponding key.
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function groupByLimit(coll, limit, iteratee, callback) {
+    var _iteratee = wrapAsync(iteratee);
+    return mapLimit$1(coll, limit, (val, iterCb) => {
+        _iteratee(val, (err, key) => {
+            if (err) return iterCb(err);
+            return iterCb(err, {key, val});
+        });
+    }, (err, mapResults) => {
+        var result = {};
+        // from MDN, handle object having an `hasOwnProperty` prop
+        var {hasOwnProperty} = Object.prototype;
+
+        for (var i = 0; i < mapResults.length; i++) {
+            if (mapResults[i]) {
+                var {key} = mapResults[i];
+                var {val} = mapResults[i];
+
+                if (hasOwnProperty.call(result, key)) {
+                    result[key].push(val);
+                } else {
+                    result[key] = [val];
+                }
+            }
+        }
+
+        return callback(err, result);
+    });
+}
+
+var groupByLimit$1 = awaitify(groupByLimit, 4);
+
+/**
+ * Returns a new object, where each value corresponds to an array of items, from
+ * `coll`, that returned the corresponding key. That is, the keys of the object
+ * correspond to the values passed to the `iteratee` callback.
+ *
+ * Note: Since this function applies the `iteratee` to each item in parallel,
+ * there is no guarantee that the `iteratee` functions will complete in order.
+ * However, the values for each key in the `result` will be in the same order as
+ * the original `coll`. For Objects, the values will roughly be in the order of
+ * the original Objects' keys (but this can vary across JavaScript engines).
+ *
+ * @name groupBy
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with a `key` to group the value under.
+ * Invoked with (value, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Result is an `Object` whoses
+ * properties are arrays of values which returned the corresponding key.
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * const files = ['dir1/file1.txt','dir2','dir4']
+ *
+ * // asynchronous function that detects file type as none, file, or directory
+ * function detectFile(file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(null, 'none');
+ *         }
+ *         callback(null, stat.isDirectory() ? 'directory' : 'file');
+ *     });
+ * }
+ *
+ * //Using callbacks
+ * async.groupBy(files, detectFile, function(err, result) {
+ *     if(err) {
+ *         console.log(err);
+ *     } else {
+ *	       console.log(result);
+ *         // {
+ *         //     file: [ 'dir1/file1.txt' ],
+ *         //     none: [ 'dir4' ],
+ *         //     directory: [ 'dir2']
+ *         // }
+ *         // result is object containing the files grouped by type
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.groupBy(files, detectFile)
+ * .then( result => {
+ *     console.log(result);
+ *     // {
+ *     //     file: [ 'dir1/file1.txt' ],
+ *     //     none: [ 'dir4' ],
+ *     //     directory: [ 'dir2']
+ *     // }
+ *     // result is object containing the files grouped by type
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.groupBy(files, detectFile);
+ *         console.log(result);
+ *         // {
+ *         //     file: [ 'dir1/file1.txt' ],
+ *         //     none: [ 'dir4' ],
+ *         //     directory: [ 'dir2']
+ *         // }
+ *         // result is object containing the files grouped by type
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function groupBy (coll, iteratee, callback) {
+    return groupByLimit$1(coll, Infinity, iteratee, callback)
+}
+
+/**
+ * The same as [`groupBy`]{@link module:Collections.groupBy} but runs only a single async operation at a time.
+ *
+ * @name groupBySeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.groupBy]{@link module:Collections.groupBy}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with a `key` to group the value under.
+ * Invoked with (value, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Result is an `Object` whose
+ * properties are arrays of values which returned the corresponding key.
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function groupBySeries (coll, iteratee, callback) {
+    return groupByLimit$1(coll, 1, iteratee, callback)
+}
+
+/**
+ * Logs the result of an `async` function to the `console`. Only works in
+ * Node.js or in browsers that support `console.log` and `console.error` (such
+ * as FF and Chrome). If multiple arguments are returned from the async
+ * function, `console.log` is called on each argument in order.
+ *
+ * @name log
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} function - The function you want to eventually apply
+ * all arguments to.
+ * @param {...*} arguments... - Any number of arguments to apply to the function.
+ * @example
+ *
+ * // in a module
+ * var hello = function(name, callback) {
+ *     setTimeout(function() {
+ *         callback(null, 'hello ' + name);
+ *     }, 1000);
+ * };
+ *
+ * // in the node repl
+ * node> async.log(hello, 'world');
+ * 'hello world'
+ */
+var log = consoleFunc('log');
+
+/**
+ * The same as [`mapValues`]{@link module:Collections.mapValues} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name mapValuesLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.mapValues]{@link module:Collections.mapValues}
+ * @category Collection
+ * @param {Object} obj - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - A function to apply to each value and key
+ * in `coll`.
+ * The iteratee should complete with the transformed value as its result.
+ * Invoked with (value, key, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. `result` is a new object consisting
+ * of each key from `obj`, with each transformed value on the right-hand side.
+ * Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function mapValuesLimit(obj, limit, iteratee, callback) {
+    callback = once(callback);
+    var newObj = {};
+    var _iteratee = wrapAsync(iteratee);
+    return eachOfLimit(limit)(obj, (val, key, next) => {
+        _iteratee(val, key, (err, result) => {
+            if (err) return next(err);
+            newObj[key] = result;
+            next(err);
+        });
+    }, err => callback(err, newObj));
+}
+
+var mapValuesLimit$1 = awaitify(mapValuesLimit, 4);
+
+/**
+ * A relative of [`map`]{@link module:Collections.map}, designed for use with objects.
+ *
+ * Produces a new Object by mapping each value of `obj` through the `iteratee`
+ * function. The `iteratee` is called each `value` and `key` from `obj` and a
+ * callback for when it has finished processing. Each of these callbacks takes
+ * two arguments: an `error`, and the transformed item from `obj`. If `iteratee`
+ * passes an error to its callback, the main `callback` (for the `mapValues`
+ * function) is immediately called with the error.
+ *
+ * Note, the order of the keys in the result is not guaranteed.  The keys will
+ * be roughly in the order they complete, (but this is very engine-specific)
+ *
+ * @name mapValues
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Object} obj - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each value and key
+ * in `coll`.
+ * The iteratee should complete with the transformed value as its result.
+ * Invoked with (value, key, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. `result` is a new object consisting
+ * of each key from `obj`, with each transformed value on the right-hand side.
+ * Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ * // file4.txt does not exist
+ *
+ * const fileMap = {
+ *     f1: 'file1.txt',
+ *     f2: 'file2.txt',
+ *     f3: 'file3.txt'
+ * };
+ *
+ * const withMissingFileMap = {
+ *     f1: 'file1.txt',
+ *     f2: 'file2.txt',
+ *     f3: 'file4.txt'
+ * };
+ *
+ * // asynchronous function that returns the file size in bytes
+ * function getFileSizeInBytes(file, key, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.mapValues(fileMap, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // result is now a map of file size in bytes for each file, e.g.
+ *         // {
+ *         //     f1: 1000,
+ *         //     f2: 2000,
+ *         //     f3: 3000
+ *         // }
+ *     }
+ * });
+ *
+ * // Error handling
+ * async.mapValues(withMissingFileMap, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     } else {
+ *         console.log(result);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.mapValues(fileMap, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ *     // result is now a map of file size in bytes for each file, e.g.
+ *     // {
+ *     //     f1: 1000,
+ *     //     f2: 2000,
+ *     //     f3: 3000
+ *     // }
+ * }).catch (err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.mapValues(withMissingFileMap, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ * }).catch (err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.mapValues(fileMap, getFileSizeInBytes);
+ *         console.log(result);
+ *         // result is now a map of file size in bytes for each file, e.g.
+ *         // {
+ *         //     f1: 1000,
+ *         //     f2: 2000,
+ *         //     f3: 3000
+ *         // }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let result = await async.mapValues(withMissingFileMap, getFileSizeInBytes);
+ *         console.log(result);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function mapValues(obj, iteratee, callback) {
+    return mapValuesLimit$1(obj, Infinity, iteratee, callback)
+}
+
+/**
+ * The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time.
+ *
+ * @name mapValuesSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.mapValues]{@link module:Collections.mapValues}
+ * @category Collection
+ * @param {Object} obj - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each value and key
+ * in `coll`.
+ * The iteratee should complete with the transformed value as its result.
+ * Invoked with (value, key, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. `result` is a new object consisting
+ * of each key from `obj`, with each transformed value on the right-hand side.
+ * Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function mapValuesSeries(obj, iteratee, callback) {
+    return mapValuesLimit$1(obj, 1, iteratee, callback)
+}
+
+/**
+ * Caches the results of an async function. When creating a hash to store
+ * function results against, the callback is omitted from the hash and an
+ * optional hash function can be used.
+ *
+ * **Note: if the async function errs, the result will not be cached and
+ * subsequent calls will call the wrapped function.**
+ *
+ * If no hash function is specified, the first argument is used as a hash key,
+ * which may work reasonably if it is a string or a data type that converts to a
+ * distinct string. Note that objects and arrays will not behave reasonably.
+ * Neither will cases where the other arguments are significant. In such cases,
+ * specify your own hash function.
+ *
+ * The cache of results is exposed as the `memo` property of the function
+ * returned by `memoize`.
+ *
+ * @name memoize
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} fn - The async function to proxy and cache results from.
+ * @param {Function} hasher - An optional function for generating a custom hash
+ * for storing results. It has all the arguments applied to it apart from the
+ * callback, and must be synchronous.
+ * @returns {AsyncFunction} a memoized version of `fn`
+ * @example
+ *
+ * var slow_fn = function(name, callback) {
+ *     // do something
+ *     callback(null, result);
+ * };
+ * var fn = async.memoize(slow_fn);
+ *
+ * // fn can now be used as if it were slow_fn
+ * fn('some name', function() {
+ *     // callback
+ * });
+ */
+function memoize(fn, hasher = v => v) {
+    var memo = Object.create(null);
+    var queues = Object.create(null);
+    var _fn = wrapAsync(fn);
+    var memoized = initialParams((args, callback) => {
+        var key = hasher(...args);
+        if (key in memo) {
+            setImmediate$1(() => callback(null, ...memo[key]));
+        } else if (key in queues) {
+            queues[key].push(callback);
+        } else {
+            queues[key] = [callback];
+            _fn(...args, (err, ...resultArgs) => {
+                // #1465 don't memoize if an error occurred
+                if (!err) {
+                    memo[key] = resultArgs;
+                }
+                var q = queues[key];
+                delete queues[key];
+                for (var i = 0, l = q.length; i < l; i++) {
+                    q[i](err, ...resultArgs);
+                }
+            });
+        }
+    });
+    memoized.memo = memo;
+    memoized.unmemoized = fn;
+    return memoized;
+}
+
+/* istanbul ignore file */
+
+/**
+ * Calls `callback` on a later loop around the event loop. In Node.js this just
+ * calls `process.nextTick`.  In the browser it will use `setImmediate` if
+ * available, otherwise `setTimeout(callback, 0)`, which means other higher
+ * priority events may precede the execution of `callback`.
+ *
+ * This is used internally for browser-compatibility purposes.
+ *
+ * @name nextTick
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @see [async.setImmediate]{@link module:Utils.setImmediate}
+ * @category Util
+ * @param {Function} callback - The function to call on a later loop around
+ * the event loop. Invoked with (args...).
+ * @param {...*} args... - any number of additional arguments to pass to the
+ * callback on the next tick.
+ * @example
+ *
+ * var call_order = [];
+ * async.nextTick(function() {
+ *     call_order.push('two');
+ *     // call_order now equals ['one','two']
+ * });
+ * call_order.push('one');
+ *
+ * async.setImmediate(function (a, b, c) {
+ *     // a, b, and c equal 1, 2, and 3
+ * }, 1, 2, 3);
+ */
+var _defer$1;
+
+if (hasNextTick) {
+    _defer$1 = process.nextTick;
+} else if (hasSetImmediate) {
+    _defer$1 = setImmediate;
+} else {
+    _defer$1 = fallback;
+}
+
+var nextTick = wrap(_defer$1);
+
+var parallel = awaitify((eachfn, tasks, callback) => {
+    var results = isArrayLike(tasks) ? [] : {};
+
+    eachfn(tasks, (task, key, taskCb) => {
+        wrapAsync(task)((err, ...result) => {
+            if (result.length < 2) {
+                [result] = result;
+            }
+            results[key] = result;
+            taskCb(err);
+        });
+    }, err => callback(err, results));
+}, 3);
+
+/**
+ * Run the `tasks` collection of functions in parallel, without waiting until
+ * the previous function has completed. If any of the functions pass an error to
+ * its callback, the main `callback` is immediately called with the value of the
+ * error. Once the `tasks` have completed, the results are passed to the final
+ * `callback` as an array.
+ *
+ * **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about
+ * parallel execution of code.  If your tasks do not use any timers or perform
+ * any I/O, they will actually be executed in series.  Any synchronous setup
+ * sections for each task will happen one after the other.  JavaScript remains
+ * single-threaded.
+ *
+ * **Hint:** Use [`reflect`]{@link module:Utils.reflect} to continue the
+ * execution of other tasks when a task fails.
+ *
+ * It is also possible to use an object instead of an array. Each property will
+ * be run as a function and the results will be passed to the final `callback`
+ * as an object instead of an array. This can be a more readable way of handling
+ * results from {@link async.parallel}.
+ *
+ * @name parallel
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of
+ * [async functions]{@link AsyncFunction} to run.
+ * Each async function can complete with any number of optional `result` values.
+ * @param {Function} [callback] - An optional callback to run once all the
+ * functions have completed successfully. This function gets a results array
+ * (or object) containing all the result arguments passed to the task callbacks.
+ * Invoked with (err, results).
+ * @returns {Promise} a promise, if a callback is not passed
+ *
+ * @example
+ *
+ * //Using Callbacks
+ * async.parallel([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ], function(err, results) {
+ *     console.log(results);
+ *     // results is equal to ['one','two'] even though
+ *     // the second function had a shorter timeout.
+ * });
+ *
+ * // an example using an object instead of an array
+ * async.parallel({
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 1);
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 2);
+ *         }, 100);
+ *     }
+ * }, function(err, results) {
+ *     console.log(results);
+ *     // results is equal to: { one: 1, two: 2 }
+ * });
+ *
+ * //Using Promises
+ * async.parallel([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ]).then(results => {
+ *     console.log(results);
+ *     // results is equal to ['one','two'] even though
+ *     // the second function had a shorter timeout.
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // an example using an object instead of an array
+ * async.parallel({
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 1);
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 2);
+ *         }, 100);
+ *     }
+ * }).then(results => {
+ *     console.log(results);
+ *     // results is equal to: { one: 1, two: 2 }
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * //Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.parallel([
+ *             function(callback) {
+ *                 setTimeout(function() {
+ *                     callback(null, 'one');
+ *                 }, 200);
+ *             },
+ *             function(callback) {
+ *                 setTimeout(function() {
+ *                     callback(null, 'two');
+ *                 }, 100);
+ *             }
+ *         ]);
+ *         console.log(results);
+ *         // results is equal to ['one','two'] even though
+ *         // the second function had a shorter timeout.
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // an example using an object instead of an array
+ * async () => {
+ *     try {
+ *         let results = await async.parallel({
+ *             one: function(callback) {
+ *                 setTimeout(function() {
+ *                     callback(null, 1);
+ *                 }, 200);
+ *             },
+ *            two: function(callback) {
+ *                 setTimeout(function() {
+ *                     callback(null, 2);
+ *                 }, 100);
+ *            }
+ *         });
+ *         console.log(results);
+ *         // results is equal to: { one: 1, two: 2 }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function parallel$1(tasks, callback) {
+    return parallel(eachOf$1, tasks, callback);
+}
+
+/**
+ * The same as [`parallel`]{@link module:ControlFlow.parallel} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name parallelLimit
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.parallel]{@link module:ControlFlow.parallel}
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of
+ * [async functions]{@link AsyncFunction} to run.
+ * Each async function can complete with any number of optional `result` values.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {Function} [callback] - An optional callback to run once all the
+ * functions have completed successfully. This function gets a results array
+ * (or object) containing all the result arguments passed to the task callbacks.
+ * Invoked with (err, results).
+ * @returns {Promise} a promise, if a callback is not passed
+ */
+function parallelLimit(tasks, limit, callback) {
+    return parallel(eachOfLimit(limit), tasks, callback);
+}
+
+/**
+ * A queue of tasks for the worker function to complete.
+ * @typedef {Iterable} QueueObject
+ * @memberOf module:ControlFlow
+ * @property {Function} length - a function returning the number of items
+ * waiting to be processed. Invoke with `queue.length()`.
+ * @property {boolean} started - a boolean indicating whether or not any
+ * items have been pushed and processed by the queue.
+ * @property {Function} running - a function returning the number of items
+ * currently being processed. Invoke with `queue.running()`.
+ * @property {Function} workersList - a function returning the array of items
+ * currently being processed. Invoke with `queue.workersList()`.
+ * @property {Function} idle - a function returning false if there are items
+ * waiting or being processed, or true if not. Invoke with `queue.idle()`.
+ * @property {number} concurrency - an integer for determining how many `worker`
+ * functions should be run in parallel. This property can be changed after a
+ * `queue` is created to alter the concurrency on-the-fly.
+ * @property {number} payload - an integer that specifies how many items are
+ * passed to the worker function at a time. only applies if this is a
+ * [cargo]{@link module:ControlFlow.cargo} object
+ * @property {AsyncFunction} push - add a new task to the `queue`. Calls `callback`
+ * once the `worker` has finished processing the task. Instead of a single task,
+ * a `tasks` array can be submitted. The respective callback is used for every
+ * task in the list. Invoke with `queue.push(task, [callback])`,
+ * @property {AsyncFunction} unshift - add a new task to the front of the `queue`.
+ * Invoke with `queue.unshift(task, [callback])`.
+ * @property {AsyncFunction} pushAsync - the same as `q.push`, except this returns
+ * a promise that rejects if an error occurs.
+ * @property {AsyncFunction} unshiftAsync - the same as `q.unshift`, except this returns
+ * a promise that rejects if an error occurs.
+ * @property {Function} remove - remove items from the queue that match a test
+ * function.  The test function will be passed an object with a `data` property,
+ * and a `priority` property, if this is a
+ * [priorityQueue]{@link module:ControlFlow.priorityQueue} object.
+ * Invoked with `queue.remove(testFn)`, where `testFn` is of the form
+ * `function ({data, priority}) {}` and returns a Boolean.
+ * @property {Function} saturated - a function that sets a callback that is
+ * called when the number of running workers hits the `concurrency` limit, and
+ * further tasks will be queued.  If the callback is omitted, `q.saturated()`
+ * returns a promise for the next occurrence.
+ * @property {Function} unsaturated - a function that sets a callback that is
+ * called when the number of running workers is less than the `concurrency` &
+ * `buffer` limits, and further tasks will not be queued. If the callback is
+ * omitted, `q.unsaturated()` returns a promise for the next occurrence.
+ * @property {number} buffer - A minimum threshold buffer in order to say that
+ * the `queue` is `unsaturated`.
+ * @property {Function} empty - a function that sets a callback that is called
+ * when the last item from the `queue` is given to a `worker`. If the callback
+ * is omitted, `q.empty()` returns a promise for the next occurrence.
+ * @property {Function} drain - a function that sets a callback that is called
+ * when the last item from the `queue` has returned from the `worker`. If the
+ * callback is omitted, `q.drain()` returns a promise for the next occurrence.
+ * @property {Function} error - a function that sets a callback that is called
+ * when a task errors. Has the signature `function(error, task)`. If the
+ * callback is omitted, `error()` returns a promise that rejects on the next
+ * error.
+ * @property {boolean} paused - a boolean for determining whether the queue is
+ * in a paused state.
+ * @property {Function} pause - a function that pauses the processing of tasks
+ * until `resume()` is called. Invoke with `queue.pause()`.
+ * @property {Function} resume - a function that resumes the processing of
+ * queued tasks when the queue is paused. Invoke with `queue.resume()`.
+ * @property {Function} kill - a function that removes the `drain` callback and
+ * empties remaining tasks from the queue forcing it to go idle. No more tasks
+ * should be pushed to the queue after calling this function. Invoke with `queue.kill()`.
+ *
+ * @example
+ * const q = async.queue(worker, 2)
+ * q.push(item1)
+ * q.push(item2)
+ * q.push(item3)
+ * // queues are iterable, spread into an array to inspect
+ * const items = [...q] // [item1, item2, item3]
+ * // or use for of
+ * for (let item of q) {
+ *     console.log(item)
+ * }
+ *
+ * q.drain(() => {
+ *     console.log('all done')
+ * })
+ * // or
+ * await q.drain()
+ */
+
+/**
+ * Creates a `queue` object with the specified `concurrency`. Tasks added to the
+ * `queue` are processed in parallel (up to the `concurrency` limit). If all
+ * `worker`s are in progress, the task is queued until one becomes available.
+ * Once a `worker` completes a `task`, that `task`'s callback is called.
+ *
+ * @name queue
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {AsyncFunction} worker - An async function for processing a queued task.
+ * If you want to handle errors from an individual task, pass a callback to
+ * `q.push()`. Invoked with (task, callback).
+ * @param {number} [concurrency=1] - An `integer` for determining how many
+ * `worker` functions should be run in parallel.  If omitted, the concurrency
+ * defaults to `1`.  If the concurrency is `0`, an error is thrown.
+ * @returns {module:ControlFlow.QueueObject} A queue object to manage the tasks. Callbacks can be
+ * attached as certain properties to listen for specific events during the
+ * lifecycle of the queue.
+ * @example
+ *
+ * // create a queue object with concurrency 2
+ * var q = async.queue(function(task, callback) {
+ *     console.log('hello ' + task.name);
+ *     callback();
+ * }, 2);
+ *
+ * // assign a callback
+ * q.drain(function() {
+ *     console.log('all items have been processed');
+ * });
+ * // or await the end
+ * await q.drain()
+ *
+ * // assign an error callback
+ * q.error(function(err, task) {
+ *     console.error('task experienced an error');
+ * });
+ *
+ * // add some items to the queue
+ * q.push({name: 'foo'}, function(err) {
+ *     console.log('finished processing foo');
+ * });
+ * // callback is optional
+ * q.push({name: 'bar'});
+ *
+ * // add some items to the queue (batch-wise)
+ * q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
+ *     console.log('finished processing item');
+ * });
+ *
+ * // add some items to the front of the queue
+ * q.unshift({name: 'bar'}, function (err) {
+ *     console.log('finished processing bar');
+ * });
+ */
+function queue$1 (worker, concurrency) {
+    var _worker = wrapAsync(worker);
+    return queue((items, cb) => {
+        _worker(items[0], cb);
+    }, concurrency, 1);
+}
+
+// Binary min-heap implementation used for priority queue.
+// Implementation is stable, i.e. push time is considered for equal priorities
+class Heap {
+    constructor() {
+        this.heap = [];
+        this.pushCount = Number.MIN_SAFE_INTEGER;
+    }
+
+    get length() {
+        return this.heap.length;
+    }
+
+    empty () {
+        this.heap = [];
+        return this;
+    }
+
+    percUp(index) {
+        let p;
+
+        while (index > 0 && smaller(this.heap[index], this.heap[p=parent(index)])) {
+            let t = this.heap[index];
+            this.heap[index] = this.heap[p];
+            this.heap[p] = t;
+
+            index = p;
+        }
+    }
+
+    percDown(index) {
+        let l;
+
+        while ((l=leftChi(index)) < this.heap.length) {
+            if (l+1 < this.heap.length && smaller(this.heap[l+1], this.heap[l])) {
+                l = l+1;
+            }
+
+            if (smaller(this.heap[index], this.heap[l])) {
+                break;
+            }
+
+            let t = this.heap[index];
+            this.heap[index] = this.heap[l];
+            this.heap[l] = t;
+
+            index = l;
+        }
+    }
+
+    push(node) {
+        node.pushCount = ++this.pushCount;
+        this.heap.push(node);
+        this.percUp(this.heap.length-1);
+    }
+
+    unshift(node) {
+        return this.heap.push(node);
+    }
+
+    shift() {
+        let [top] = this.heap;
+
+        this.heap[0] = this.heap[this.heap.length-1];
+        this.heap.pop();
+        this.percDown(0);
+
+        return top;
+    }
+
+    toArray() {
+        return [...this];
+    }
+
+    *[Symbol.iterator] () {
+        for (let i = 0; i < this.heap.length; i++) {
+            yield this.heap[i].data;
+        }
+    }
+
+    remove (testFn) {
+        let j = 0;
+        for (let i = 0; i < this.heap.length; i++) {
+            if (!testFn(this.heap[i])) {
+                this.heap[j] = this.heap[i];
+                j++;
+            }
+        }
+
+        this.heap.splice(j);
+
+        for (let i = parent(this.heap.length-1); i >= 0; i--) {
+            this.percDown(i);
+        }
+
+        return this;
+    }
+}
+
+function leftChi(i) {
+    return (i<<1)+1;
+}
+
+function parent(i) {
+    return ((i+1)>>1)-1;
+}
+
+function smaller(x, y) {
+    if (x.priority !== y.priority) {
+        return x.priority < y.priority;
+    }
+    else {
+        return x.pushCount < y.pushCount;
+    }
+}
+
+/**
+ * The same as [async.queue]{@link module:ControlFlow.queue} only tasks are assigned a priority and
+ * completed in ascending priority order.
+ *
+ * @name priorityQueue
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.queue]{@link module:ControlFlow.queue}
+ * @category Control Flow
+ * @param {AsyncFunction} worker - An async function for processing a queued task.
+ * If you want to handle errors from an individual task, pass a callback to
+ * `q.push()`.
+ * Invoked with (task, callback).
+ * @param {number} concurrency - An `integer` for determining how many `worker`
+ * functions should be run in parallel.  If omitted, the concurrency defaults to
+ * `1`.  If the concurrency is `0`, an error is thrown.
+ * @returns {module:ControlFlow.QueueObject} A priorityQueue object to manage the tasks. There are three
+ * differences between `queue` and `priorityQueue` objects:
+ * * `push(task, priority, [callback])` - `priority` should be a number. If an
+ *   array of `tasks` is given, all tasks will be assigned the same priority.
+ * * `pushAsync(task, priority, [callback])` - the same as `priorityQueue.push`,
+ *   except this returns a promise that rejects if an error occurs.
+ * * The `unshift` and `unshiftAsync` methods were removed.
+ */
+function priorityQueue(worker, concurrency) {
+    // Start with a normal queue
+    var q = queue$1(worker, concurrency);
+
+    var {
+        push,
+        pushAsync
+    } = q;
+
+    q._tasks = new Heap();
+    q._createTaskItem = ({data, priority}, callback) => {
+        return {
+            data,
+            priority,
+            callback
+        };
+    };
+
+    function createDataItems(tasks, priority) {
+        if (!Array.isArray(tasks)) {
+            return {data: tasks, priority};
+        }
+        return tasks.map(data => { return {data, priority}; });
+    }
+
+    // Override push to accept second parameter representing priority
+    q.push = function(data, priority = 0, callback) {
+        return push(createDataItems(data, priority), callback);
+    };
+
+    q.pushAsync = function(data, priority = 0, callback) {
+        return pushAsync(createDataItems(data, priority), callback);
+    };
+
+    // Remove unshift functions
+    delete q.unshift;
+    delete q.unshiftAsync;
+
+    return q;
+}
+
+/**
+ * Runs the `tasks` array of functions in parallel, without waiting until the
+ * previous function has completed. Once any of the `tasks` complete or pass an
+ * error to its callback, the main `callback` is immediately called. It's
+ * equivalent to `Promise.race()`.
+ *
+ * @name race
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array} tasks - An array containing [async functions]{@link AsyncFunction}
+ * to run. Each function can complete with an optional `result` value.
+ * @param {Function} callback - A callback to run once any of the functions have
+ * completed. This function gets an error or result from the first function that
+ * completed. Invoked with (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * async.race([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ],
+ * // main callback
+ * function(err, result) {
+ *     // the result will be equal to 'two' as it finishes earlier
+ * });
+ */
+function race(tasks, callback) {
+    callback = once(callback);
+    if (!Array.isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions'));
+    if (!tasks.length) return callback();
+    for (var i = 0, l = tasks.length; i < l; i++) {
+        wrapAsync(tasks[i])(callback);
+    }
+}
+
+var race$1 = awaitify(race, 2);
+
+/**
+ * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order.
+ *
+ * @name reduceRight
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.reduce]{@link module:Collections.reduce}
+ * @alias foldr
+ * @category Collection
+ * @param {Array} array - A collection to iterate over.
+ * @param {*} memo - The initial state of the reduction.
+ * @param {AsyncFunction} iteratee - A function applied to each item in the
+ * array to produce the next step in the reduction.
+ * The `iteratee` should complete with the next state of the reduction.
+ * If the iteratee completes with an error, the reduction is stopped and the
+ * main `callback` is immediately called with the error.
+ * Invoked with (memo, item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result is the reduced value. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function reduceRight (array, memo, iteratee, callback) {
+    var reversed = [...array].reverse();
+    return reduce$1(reversed, memo, iteratee, callback);
+}
+
+/**
+ * Wraps the async function in another function that always completes with a
+ * result object, even when it errors.
+ *
+ * The result object has either the property `error` or `value`.
+ *
+ * @name reflect
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} fn - The async function you want to wrap
+ * @returns {Function} - A function that always passes null to it's callback as
+ * the error. The second argument to the callback will be an `object` with
+ * either an `error` or a `value` property.
+ * @example
+ *
+ * async.parallel([
+ *     async.reflect(function(callback) {
+ *         // do some stuff ...
+ *         callback(null, 'one');
+ *     }),
+ *     async.reflect(function(callback) {
+ *         // do some more stuff but error ...
+ *         callback('bad stuff happened');
+ *     }),
+ *     async.reflect(function(callback) {
+ *         // do some more stuff ...
+ *         callback(null, 'two');
+ *     })
+ * ],
+ * // optional callback
+ * function(err, results) {
+ *     // values
+ *     // results[0].value = 'one'
+ *     // results[1].error = 'bad stuff happened'
+ *     // results[2].value = 'two'
+ * });
+ */
+function reflect(fn) {
+    var _fn = wrapAsync(fn);
+    return initialParams(function reflectOn(args, reflectCallback) {
+        args.push((error, ...cbArgs) => {
+            let retVal = {};
+            if (error) {
+                retVal.error = error;
+            }
+            if (cbArgs.length > 0){
+                var value = cbArgs;
+                if (cbArgs.length <= 1) {
+                    [value] = cbArgs;
+                }
+                retVal.value = value;
+            }
+            reflectCallback(null, retVal);
+        });
+
+        return _fn.apply(this, args);
+    });
+}
+
+/**
+ * A helper function that wraps an array or an object of functions with `reflect`.
+ *
+ * @name reflectAll
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @see [async.reflect]{@link module:Utils.reflect}
+ * @category Util
+ * @param {Array|Object|Iterable} tasks - The collection of
+ * [async functions]{@link AsyncFunction} to wrap in `async.reflect`.
+ * @returns {Array} Returns an array of async functions, each wrapped in
+ * `async.reflect`
+ * @example
+ *
+ * let tasks = [
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         // do some more stuff but error ...
+ *         callback(new Error('bad stuff happened'));
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ];
+ *
+ * async.parallel(async.reflectAll(tasks),
+ * // optional callback
+ * function(err, results) {
+ *     // values
+ *     // results[0].value = 'one'
+ *     // results[1].error = Error('bad stuff happened')
+ *     // results[2].value = 'two'
+ * });
+ *
+ * // an example using an object instead of an array
+ * let tasks = {
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         callback('two');
+ *     },
+ *     three: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'three');
+ *         }, 100);
+ *     }
+ * };
+ *
+ * async.parallel(async.reflectAll(tasks),
+ * // optional callback
+ * function(err, results) {
+ *     // values
+ *     // results.one.value = 'one'
+ *     // results.two.error = 'two'
+ *     // results.three.value = 'three'
+ * });
+ */
+function reflectAll(tasks) {
+    var results;
+    if (Array.isArray(tasks)) {
+        results = tasks.map(reflect);
+    } else {
+        results = {};
+        Object.keys(tasks).forEach(key => {
+            results[key] = reflect.call(this, tasks[key]);
+        });
+    }
+    return results;
+}
+
+function reject(eachfn, arr, _iteratee, callback) {
+    const iteratee = wrapAsync(_iteratee);
+    return _filter(eachfn, arr, (value, cb) => {
+        iteratee(value, (err, v) => {
+            cb(err, !v);
+        });
+    }, callback);
+}
+
+/**
+ * The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test.
+ *
+ * @name reject
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.filter]{@link module:Collections.filter}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - An async truth test to apply to each item in
+ * `coll`.
+ * The should complete with a boolean value as its `result`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ *
+ * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt'];
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.reject(fileList, fileExists, function(err, results) {
+ *    // [ 'dir3/file6.txt' ]
+ *    // results now equals an array of the non-existing files
+ * });
+ *
+ * // Using Promises
+ * async.reject(fileList, fileExists)
+ * .then( results => {
+ *     console.log(results);
+ *     // [ 'dir3/file6.txt' ]
+ *     // results now equals an array of the non-existing files
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.reject(fileList, fileExists);
+ *         console.log(results);
+ *         // [ 'dir3/file6.txt' ]
+ *         // results now equals an array of the non-existing files
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function reject$1 (coll, iteratee, callback) {
+    return reject(eachOf$1, coll, iteratee, callback)
+}
+var reject$2 = awaitify(reject$1, 3);
+
+/**
+ * The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name rejectLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.reject]{@link module:Collections.reject}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {Function} iteratee - An async truth test to apply to each item in
+ * `coll`.
+ * The should complete with a boolean value as its `result`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function rejectLimit (coll, limit, iteratee, callback) {
+    return reject(eachOfLimit(limit), coll, iteratee, callback)
+}
+var rejectLimit$1 = awaitify(rejectLimit, 4);
+
+/**
+ * The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time.
+ *
+ * @name rejectSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.reject]{@link module:Collections.reject}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - An async truth test to apply to each item in
+ * `coll`.
+ * The should complete with a boolean value as its `result`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function rejectSeries (coll, iteratee, callback) {
+    return reject(eachOfSeries$1, coll, iteratee, callback)
+}
+var rejectSeries$1 = awaitify(rejectSeries, 3);
+
+function constant$1(value) {
+    return function () {
+        return value;
+    }
+}
+
+/**
+ * Attempts to get a successful response from `task` no more than `times` times
+ * before returning an error. If the task is successful, the `callback` will be
+ * passed the result of the successful task. If all attempts fail, the callback
+ * will be passed the error and result (if any) of the final attempt.
+ *
+ * @name retry
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @see [async.retryable]{@link module:ControlFlow.retryable}
+ * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an
+ * object with `times` and `interval` or a number.
+ * * `times` - The number of attempts to make before giving up.  The default
+ *   is `5`.
+ * * `interval` - The time to wait between retries, in milliseconds.  The
+ *   default is `0`. The interval may also be specified as a function of the
+ *   retry count (see example).
+ * * `errorFilter` - An optional synchronous function that is invoked on
+ *   erroneous result. If it returns `true` the retry attempts will continue;
+ *   if the function returns `false` the retry flow is aborted with the current
+ *   attempt's error and result being returned to the final callback.
+ *   Invoked with (err).
+ * * If `opts` is a number, the number specifies the number of times to retry,
+ *   with the default interval of `0`.
+ * @param {AsyncFunction} task - An async function to retry.
+ * Invoked with (callback).
+ * @param {Function} [callback] - An optional callback which is called when the
+ * task has succeeded, or after the final failed attempt. It receives the `err`
+ * and `result` arguments of the last attempt at completing the `task`. Invoked
+ * with (err, results).
+ * @returns {Promise} a promise if no callback provided
+ *
+ * @example
+ *
+ * // The `retry` function can be used as a stand-alone control flow by passing
+ * // a callback, as shown below:
+ *
+ * // try calling apiMethod 3 times
+ * async.retry(3, apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // try calling apiMethod 3 times, waiting 200 ms between each retry
+ * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // try calling apiMethod 10 times with exponential backoff
+ * // (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds)
+ * async.retry({
+ *   times: 10,
+ *   interval: function(retryCount) {
+ *     return 50 * Math.pow(2, retryCount);
+ *   }
+ * }, apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // try calling apiMethod the default 5 times no delay between each retry
+ * async.retry(apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // try calling apiMethod only when error condition satisfies, all other
+ * // errors will abort the retry control flow and return to final callback
+ * async.retry({
+ *   errorFilter: function(err) {
+ *     return err.message === 'Temporary error'; // only retry on a specific error
+ *   }
+ * }, apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // to retry individual methods that are not as reliable within other
+ * // control flow functions, use the `retryable` wrapper:
+ * async.auto({
+ *     users: api.getUsers.bind(api),
+ *     payments: async.retryable(3, api.getPayments.bind(api))
+ * }, function(err, results) {
+ *     // do something with the results
+ * });
+ *
+ */
+const DEFAULT_TIMES = 5;
+const DEFAULT_INTERVAL = 0;
+
+function retry(opts, task, callback) {
+    var options = {
+        times: DEFAULT_TIMES,
+        intervalFunc: constant$1(DEFAULT_INTERVAL)
+    };
+
+    if (arguments.length < 3 && typeof opts === 'function') {
+        callback = task || promiseCallback();
+        task = opts;
+    } else {
+        parseTimes(options, opts);
+        callback = callback || promiseCallback();
+    }
+
+    if (typeof task !== 'function') {
+        throw new Error("Invalid arguments for async.retry");
+    }
+
+    var _task = wrapAsync(task);
+
+    var attempt = 1;
+    function retryAttempt() {
+        _task((err, ...args) => {
+            if (err === false) return
+            if (err && attempt++ < options.times &&
+                (typeof options.errorFilter != 'function' ||
+                    options.errorFilter(err))) {
+                setTimeout(retryAttempt, options.intervalFunc(attempt - 1));
+            } else {
+                callback(err, ...args);
+            }
+        });
+    }
+
+    retryAttempt();
+    return callback[PROMISE_SYMBOL]
+}
+
+function parseTimes(acc, t) {
+    if (typeof t === 'object') {
+        acc.times = +t.times || DEFAULT_TIMES;
+
+        acc.intervalFunc = typeof t.interval === 'function' ?
+            t.interval :
+            constant$1(+t.interval || DEFAULT_INTERVAL);
+
+        acc.errorFilter = t.errorFilter;
+    } else if (typeof t === 'number' || typeof t === 'string') {
+        acc.times = +t || DEFAULT_TIMES;
+    } else {
+        throw new Error("Invalid arguments for async.retry");
+    }
+}
+
+/**
+ * A close relative of [`retry`]{@link module:ControlFlow.retry}.  This method
+ * wraps a task and makes it retryable, rather than immediately calling it
+ * with retries.
+ *
+ * @name retryable
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.retry]{@link module:ControlFlow.retry}
+ * @category Control Flow
+ * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional
+ * options, exactly the same as from `retry`, except for a `opts.arity` that
+ * is the arity of the `task` function, defaulting to `task.length`
+ * @param {AsyncFunction} task - the asynchronous function to wrap.
+ * This function will be passed any arguments passed to the returned wrapper.
+ * Invoked with (...args, callback).
+ * @returns {AsyncFunction} The wrapped function, which when invoked, will
+ * retry on an error, based on the parameters specified in `opts`.
+ * This function will accept the same parameters as `task`.
+ * @example
+ *
+ * async.auto({
+ *     dep1: async.retryable(3, getFromFlakyService),
+ *     process: ["dep1", async.retryable(3, function (results, cb) {
+ *         maybeProcessData(results.dep1, cb);
+ *     })]
+ * }, callback);
+ */
+function retryable (opts, task) {
+    if (!task) {
+        task = opts;
+        opts = null;
+    }
+    let arity = (opts && opts.arity) || task.length;
+    if (isAsync(task)) {
+        arity += 1;
+    }
+    var _task = wrapAsync(task);
+    return initialParams((args, callback) => {
+        if (args.length < arity - 1 || callback == null) {
+            args.push(callback);
+            callback = promiseCallback();
+        }
+        function taskFn(cb) {
+            _task(...args, cb);
+        }
+
+        if (opts) retry(opts, taskFn, callback);
+        else retry(taskFn, callback);
+
+        return callback[PROMISE_SYMBOL]
+    });
+}
+
+/**
+ * Run the functions in the `tasks` collection in series, each one running once
+ * the previous function has completed. If any functions in the series pass an
+ * error to its callback, no more functions are run, and `callback` is
+ * immediately called with the value of the error. Otherwise, `callback`
+ * receives an array of results when `tasks` have completed.
+ *
+ * It is also possible to use an object instead of an array. Each property will
+ * be run as a function, and the results will be passed to the final `callback`
+ * as an object instead of an array. This can be a more readable way of handling
+ *  results from {@link async.series}.
+ *
+ * **Note** that while many implementations preserve the order of object
+ * properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6)
+ * explicitly states that
+ *
+ * > The mechanics and order of enumerating the properties is not specified.
+ *
+ * So if you rely on the order in which your series of functions are executed,
+ * and want this to work on all platforms, consider using an array.
+ *
+ * @name series
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing
+ * [async functions]{@link AsyncFunction} to run in series.
+ * Each function can complete with any number of optional `result` values.
+ * @param {Function} [callback] - An optional callback to run once all the
+ * functions have completed. This function gets a results array (or object)
+ * containing all the result arguments passed to the `task` callbacks. Invoked
+ * with (err, result).
+ * @return {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * //Using Callbacks
+ * async.series([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             // do some async task
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             // then do another async task
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ], function(err, results) {
+ *     console.log(results);
+ *     // results is equal to ['one','two']
+ * });
+ *
+ * // an example using objects instead of arrays
+ * async.series({
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             // do some async task
+ *             callback(null, 1);
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         setTimeout(function() {
+ *             // then do another async task
+ *             callback(null, 2);
+ *         }, 100);
+ *     }
+ * }, function(err, results) {
+ *     console.log(results);
+ *     // results is equal to: { one: 1, two: 2 }
+ * });
+ *
+ * //Using Promises
+ * async.series([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ]).then(results => {
+ *     console.log(results);
+ *     // results is equal to ['one','two']
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // an example using an object instead of an array
+ * async.series({
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             // do some async task
+ *             callback(null, 1);
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         setTimeout(function() {
+ *             // then do another async task
+ *             callback(null, 2);
+ *         }, 100);
+ *     }
+ * }).then(results => {
+ *     console.log(results);
+ *     // results is equal to: { one: 1, two: 2 }
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * //Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.series([
+ *             function(callback) {
+ *                 setTimeout(function() {
+ *                     // do some async task
+ *                     callback(null, 'one');
+ *                 }, 200);
+ *             },
+ *             function(callback) {
+ *                 setTimeout(function() {
+ *                     // then do another async task
+ *                     callback(null, 'two');
+ *                 }, 100);
+ *             }
+ *         ]);
+ *         console.log(results);
+ *         // results is equal to ['one','two']
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // an example using an object instead of an array
+ * async () => {
+ *     try {
+ *         let results = await async.parallel({
+ *             one: function(callback) {
+ *                 setTimeout(function() {
+ *                     // do some async task
+ *                     callback(null, 1);
+ *                 }, 200);
+ *             },
+ *            two: function(callback) {
+ *                 setTimeout(function() {
+ *                     // then do another async task
+ *                     callback(null, 2);
+ *                 }, 100);
+ *            }
+ *         });
+ *         console.log(results);
+ *         // results is equal to: { one: 1, two: 2 }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function series(tasks, callback) {
+    return parallel(eachOfSeries$1, tasks, callback);
+}
+
+/**
+ * Returns `true` if at least one element in the `coll` satisfies an async test.
+ * If any iteratee call returns `true`, the main `callback` is immediately
+ * called.
+ *
+ * @name some
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias any
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collections in parallel.
+ * The iteratee should complete with a boolean `result` value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the iteratee functions have finished.
+ * Result will be either `true` or `false` depending on the values of the async
+ * tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists,
+ *    function(err, result) {
+ *        console.log(result);
+ *        // true
+ *        // result is true since some file in the list exists
+ *    }
+ *);
+ *
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists,
+ *    function(err, result) {
+ *        console.log(result);
+ *        // false
+ *        // result is false since none of the files exists
+ *    }
+ *);
+ *
+ * // Using Promises
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // true
+ *     // result is true since some file in the list exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // false
+ *     // result is false since none of the files exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists);
+ *         console.log(result);
+ *         // true
+ *         // result is true since some file in the list exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * async () => {
+ *     try {
+ *         let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists);
+ *         console.log(result);
+ *         // false
+ *         // result is false since none of the files exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function some(coll, iteratee, callback) {
+    return _createTester(Boolean, res => res)(eachOf$1, coll, iteratee, callback)
+}
+var some$1 = awaitify(some, 3);
+
+/**
+ * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name someLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.some]{@link module:Collections.some}
+ * @alias anyLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collections in parallel.
+ * The iteratee should complete with a boolean `result` value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the iteratee functions have finished.
+ * Result will be either `true` or `false` depending on the values of the async
+ * tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function someLimit(coll, limit, iteratee, callback) {
+    return _createTester(Boolean, res => res)(eachOfLimit(limit), coll, iteratee, callback)
+}
+var someLimit$1 = awaitify(someLimit, 4);
+
+/**
+ * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time.
+ *
+ * @name someSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.some]{@link module:Collections.some}
+ * @alias anySeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collections in series.
+ * The iteratee should complete with a boolean `result` value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the iteratee functions have finished.
+ * Result will be either `true` or `false` depending on the values of the async
+ * tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function someSeries(coll, iteratee, callback) {
+    return _createTester(Boolean, res => res)(eachOfSeries$1, coll, iteratee, callback)
+}
+var someSeries$1 = awaitify(someSeries, 3);
+
+/**
+ * Sorts a list by the results of running each `coll` value through an async
+ * `iteratee`.
+ *
+ * @name sortBy
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with a value to use as the sort criteria as
+ * its `result`.
+ * Invoked with (item, callback).
+ * @param {Function} callback - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is the items
+ * from the original `coll` sorted by the values returned by the `iteratee`
+ * calls. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback passed
+ * @example
+ *
+ * // bigfile.txt is a file that is 251100 bytes in size
+ * // mediumfile.txt is a file that is 11000 bytes in size
+ * // smallfile.txt is a file that is 121 bytes in size
+ *
+ * // asynchronous function that returns the file size in bytes
+ * function getFileSizeInBytes(file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes,
+ *     function(err, results) {
+ *         if (err) {
+ *             console.log(err);
+ *         } else {
+ *             console.log(results);
+ *             // results is now the original array of files sorted by
+ *             // file size (ascending by default), e.g.
+ *             // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+ *         }
+ *     }
+ * );
+ *
+ * // By modifying the callback parameter the
+ * // sorting order can be influenced:
+ *
+ * // ascending order
+ * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], function(file, callback) {
+ *     getFileSizeInBytes(file, function(getFileSizeErr, fileSize) {
+ *         if (getFileSizeErr) return callback(getFileSizeErr);
+ *         callback(null, fileSize);
+ *     });
+ * }, function(err, results) {
+ *         if (err) {
+ *             console.log(err);
+ *         } else {
+ *             console.log(results);
+ *             // results is now the original array of files sorted by
+ *             // file size (ascending by default), e.g.
+ *             // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+ *         }
+ *     }
+ * );
+ *
+ * // descending order
+ * async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], function(file, callback) {
+ *     getFileSizeInBytes(file, function(getFileSizeErr, fileSize) {
+ *         if (getFileSizeErr) {
+ *             return callback(getFileSizeErr);
+ *         }
+ *         callback(null, fileSize * -1);
+ *     });
+ * }, function(err, results) {
+ *         if (err) {
+ *             console.log(err);
+ *         } else {
+ *             console.log(results);
+ *             // results is now the original array of files sorted by
+ *             // file size (ascending by default), e.g.
+ *             // [ 'bigfile.txt', 'mediumfile.txt', 'smallfile.txt']
+ *         }
+ *     }
+ * );
+ *
+ * // Error handling
+ * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes,
+ *     function(err, results) {
+ *         if (err) {
+ *             console.log(err);
+ *             // [ Error: ENOENT: no such file or directory ]
+ *         } else {
+ *             console.log(results);
+ *         }
+ *     }
+ * );
+ *
+ * // Using Promises
+ * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes)
+ * .then( results => {
+ *     console.log(results);
+ *     // results is now the original array of files sorted by
+ *     // file size (ascending by default), e.g.
+ *     // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error handling
+ * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes)
+ * .then( results => {
+ *     console.log(results);
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * (async () => {
+ *     try {
+ *         let results = await async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes);
+ *         console.log(results);
+ *         // results is now the original array of files sorted by
+ *         // file size (ascending by default), e.g.
+ *         // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * })();
+ *
+ * // Error handling
+ * async () => {
+ *     try {
+ *         let results = await async.sortBy(['missingfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes);
+ *         console.log(results);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function sortBy (coll, iteratee, callback) {
+    var _iteratee = wrapAsync(iteratee);
+    return map$1(coll, (x, iterCb) => {
+        _iteratee(x, (err, criteria) => {
+            if (err) return iterCb(err);
+            iterCb(err, {value: x, criteria});
+        });
+    }, (err, results) => {
+        if (err) return callback(err);
+        callback(null, results.sort(comparator).map(v => v.value));
+    });
+
+    function comparator(left, right) {
+        var a = left.criteria, b = right.criteria;
+        return a < b ? -1 : a > b ? 1 : 0;
+    }
+}
+var sortBy$1 = awaitify(sortBy, 3);
+
+/**
+ * Sets a time limit on an asynchronous function. If the function does not call
+ * its callback within the specified milliseconds, it will be called with a
+ * timeout error. The code property for the error object will be `'ETIMEDOUT'`.
+ *
+ * @name timeout
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} asyncFn - The async function to limit in time.
+ * @param {number} milliseconds - The specified time limit.
+ * @param {*} [info] - Any variable you want attached (`string`, `object`, etc)
+ * to timeout Error for more information..
+ * @returns {AsyncFunction} Returns a wrapped function that can be used with any
+ * of the control flow functions.
+ * Invoke this function with the same parameters as you would `asyncFunc`.
+ * @example
+ *
+ * function myFunction(foo, callback) {
+ *     doAsyncTask(foo, function(err, data) {
+ *         // handle errors
+ *         if (err) return callback(err);
+ *
+ *         // do some stuff ...
+ *
+ *         // return processed data
+ *         return callback(null, data);
+ *     });
+ * }
+ *
+ * var wrapped = async.timeout(myFunction, 1000);
+ *
+ * // call `wrapped` as you would `myFunction`
+ * wrapped({ bar: 'bar' }, function(err, data) {
+ *     // if `myFunction` takes < 1000 ms to execute, `err`
+ *     // and `data` will have their expected values
+ *
+ *     // else `err` will be an Error with the code 'ETIMEDOUT'
+ * });
+ */
+function timeout(asyncFn, milliseconds, info) {
+    var fn = wrapAsync(asyncFn);
+
+    return initialParams((args, callback) => {
+        var timedOut = false;
+        var timer;
+
+        function timeoutCallback() {
+            var name = asyncFn.name || 'anonymous';
+            var error  = new Error('Callback function "' + name + '" timed out.');
+            error.code = 'ETIMEDOUT';
+            if (info) {
+                error.info = info;
+            }
+            timedOut = true;
+            callback(error);
+        }
+
+        args.push((...cbArgs) => {
+            if (!timedOut) {
+                callback(...cbArgs);
+                clearTimeout(timer);
+            }
+        });
+
+        // setup timer and call original function
+        timer = setTimeout(timeoutCallback, milliseconds);
+        fn(...args);
+    });
+}
+
+function range(size) {
+    var result = Array(size);
+    while (size--) {
+        result[size] = size;
+    }
+    return result;
+}
+
+/**
+ * The same as [times]{@link module:ControlFlow.times} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name timesLimit
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.times]{@link module:ControlFlow.times}
+ * @category Control Flow
+ * @param {number} count - The number of times to run the function.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - The async function to call `n` times.
+ * Invoked with the iteration index and a callback: (n, next).
+ * @param {Function} callback - see [async.map]{@link module:Collections.map}.
+ * @returns {Promise} a promise, if no callback is provided
+ */
+function timesLimit(count, limit, iteratee, callback) {
+    var _iteratee = wrapAsync(iteratee);
+    return mapLimit$1(range(count), limit, _iteratee, callback);
+}
+
+/**
+ * Calls the `iteratee` function `n` times, and accumulates results in the same
+ * manner you would use with [map]{@link module:Collections.map}.
+ *
+ * @name times
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.map]{@link module:Collections.map}
+ * @category Control Flow
+ * @param {number} n - The number of times to run the function.
+ * @param {AsyncFunction} iteratee - The async function to call `n` times.
+ * Invoked with the iteration index and a callback: (n, next).
+ * @param {Function} callback - see {@link module:Collections.map}.
+ * @returns {Promise} a promise, if no callback is provided
+ * @example
+ *
+ * // Pretend this is some complicated async factory
+ * var createUser = function(id, callback) {
+ *     callback(null, {
+ *         id: 'user' + id
+ *     });
+ * };
+ *
+ * // generate 5 users
+ * async.times(5, function(n, next) {
+ *     createUser(n, function(err, user) {
+ *         next(err, user);
+ *     });
+ * }, function(err, users) {
+ *     // we should now have 5 users
+ * });
+ */
+function times (n, iteratee, callback) {
+    return timesLimit(n, Infinity, iteratee, callback)
+}
+
+/**
+ * The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time.
+ *
+ * @name timesSeries
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.times]{@link module:ControlFlow.times}
+ * @category Control Flow
+ * @param {number} n - The number of times to run the function.
+ * @param {AsyncFunction} iteratee - The async function to call `n` times.
+ * Invoked with the iteration index and a callback: (n, next).
+ * @param {Function} callback - see {@link module:Collections.map}.
+ * @returns {Promise} a promise, if no callback is provided
+ */
+function timesSeries (n, iteratee, callback) {
+    return timesLimit(n, 1, iteratee, callback)
+}
+
+/**
+ * A relative of `reduce`.  Takes an Object or Array, and iterates over each
+ * element in parallel, each step potentially mutating an `accumulator` value.
+ * The type of the accumulator defaults to the type of collection passed in.
+ *
+ * @name transform
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {*} [accumulator] - The initial state of the transform.  If omitted,
+ * it will default to an empty Object or Array, depending on the type of `coll`
+ * @param {AsyncFunction} iteratee - A function applied to each item in the
+ * collection that potentially modifies the accumulator.
+ * Invoked with (accumulator, item, key, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result is the transformed accumulator.
+ * Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ *
+ * // helper function that returns human-readable size format from bytes
+ * function formatBytes(bytes, decimals = 2) {
+ *   // implementation not included for brevity
+ *   return humanReadbleFilesize;
+ * }
+ *
+ * const fileList = ['file1.txt','file2.txt','file3.txt'];
+ *
+ * // asynchronous function that returns the file size, transformed to human-readable format
+ * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc.
+ * function transformFileSize(acc, value, key, callback) {
+ *     fs.stat(value, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         acc[key] = formatBytes(stat.size);
+ *         callback(null);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.transform(fileList, transformFileSize, function(err, result) {
+ *     if(err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.transform(fileList, transformFileSize)
+ * .then(result => {
+ *     console.log(result);
+ *     // [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * (async () => {
+ *     try {
+ *         let result = await async.transform(fileList, transformFileSize);
+ *         console.log(result);
+ *         // [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * })();
+ *
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ *
+ * // helper function that returns human-readable size format from bytes
+ * function formatBytes(bytes, decimals = 2) {
+ *   // implementation not included for brevity
+ *   return humanReadbleFilesize;
+ * }
+ *
+ * const fileMap = { f1: 'file1.txt', f2: 'file2.txt', f3: 'file3.txt' };
+ *
+ * // asynchronous function that returns the file size, transformed to human-readable format
+ * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc.
+ * function transformFileSize(acc, value, key, callback) {
+ *     fs.stat(value, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         acc[key] = formatBytes(stat.size);
+ *         callback(null);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.transform(fileMap, transformFileSize, function(err, result) {
+ *     if(err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.transform(fileMap, transformFileSize)
+ * .then(result => {
+ *     console.log(result);
+ *     // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.transform(fileMap, transformFileSize);
+ *         console.log(result);
+ *         // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function transform (coll, accumulator, iteratee, callback) {
+    if (arguments.length <= 3 && typeof accumulator === 'function') {
+        callback = iteratee;
+        iteratee = accumulator;
+        accumulator = Array.isArray(coll) ? [] : {};
+    }
+    callback = once(callback || promiseCallback());
+    var _iteratee = wrapAsync(iteratee);
+
+    eachOf$1(coll, (v, k, cb) => {
+        _iteratee(accumulator, v, k, cb);
+    }, err => callback(err, accumulator));
+    return callback[PROMISE_SYMBOL]
+}
+
+/**
+ * It runs each task in series but stops whenever any of the functions were
+ * successful. If one of the tasks were successful, the `callback` will be
+ * passed the result of the successful task. If all tasks fail, the callback
+ * will be passed the error and result (if any) of the final attempt.
+ *
+ * @name tryEach
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing functions to
+ * run, each function is passed a `callback(err, result)` it must call on
+ * completion with an error `err` (which can be `null`) and an optional `result`
+ * value.
+ * @param {Function} [callback] - An optional callback which is called when one
+ * of the tasks has succeeded, or all have failed. It receives the `err` and
+ * `result` arguments of the last attempt at completing the `task`. Invoked with
+ * (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ * async.tryEach([
+ *     function getDataFromFirstWebsite(callback) {
+ *         // Try getting the data from the first website
+ *         callback(err, data);
+ *     },
+ *     function getDataFromSecondWebsite(callback) {
+ *         // First website failed,
+ *         // Try getting the data from the backup website
+ *         callback(err, data);
+ *     }
+ * ],
+ * // optional callback
+ * function(err, results) {
+ *     Now do something with the data.
+ * });
+ *
+ */
+function tryEach(tasks, callback) {
+    var error = null;
+    var result;
+    return eachSeries$1(tasks, (task, taskCb) => {
+        wrapAsync(task)((err, ...args) => {
+            if (err === false) return taskCb(err);
+
+            if (args.length < 2) {
+                [result] = args;
+            } else {
+                result = args;
+            }
+            error = err;
+            taskCb(err ? null : {});
+        });
+    }, () => callback(error, result));
+}
+
+var tryEach$1 = awaitify(tryEach);
+
+/**
+ * Undoes a [memoize]{@link module:Utils.memoize}d function, reverting it to the original,
+ * unmemoized form. Handy for testing.
+ *
+ * @name unmemoize
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @see [async.memoize]{@link module:Utils.memoize}
+ * @category Util
+ * @param {AsyncFunction} fn - the memoized function
+ * @returns {AsyncFunction} a function that calls the original unmemoized function
+ */
+function unmemoize(fn) {
+    return (...args) => {
+        return (fn.unmemoized || fn)(...args);
+    };
+}
+
+/**
+ * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when
+ * stopped, or an error occurs.
+ *
+ * @name whilst
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {AsyncFunction} test - asynchronous truth test to perform before each
+ * execution of `iteratee`. Invoked with ().
+ * @param {AsyncFunction} iteratee - An async function which is called each time
+ * `test` passes. Invoked with (callback).
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has failed and repeated execution of `iteratee` has stopped. `callback`
+ * will be passed an error and any arguments passed to the final `iteratee`'s
+ * callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * var count = 0;
+ * async.whilst(
+ *     function test(cb) { cb(null, count < 5); },
+ *     function iter(callback) {
+ *         count++;
+ *         setTimeout(function() {
+ *             callback(null, count);
+ *         }, 1000);
+ *     },
+ *     function (err, n) {
+ *         // 5 seconds have passed, n = 5
+ *     }
+ * );
+ */
+function whilst(test, iteratee, callback) {
+    callback = onlyOnce(callback);
+    var _fn = wrapAsync(iteratee);
+    var _test = wrapAsync(test);
+    var results = [];
+
+    function next(err, ...rest) {
+        if (err) return callback(err);
+        results = rest;
+        if (err === false) return;
+        _test(check);
+    }
+
+    function check(err, truth) {
+        if (err) return callback(err);
+        if (err === false) return;
+        if (!truth) return callback(null, ...results);
+        _fn(next);
+    }
+
+    return _test(check);
+}
+var whilst$1 = awaitify(whilst, 3);
+
+/**
+ * Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when
+ * stopped, or an error occurs. `callback` will be passed an error and any
+ * arguments passed to the final `iteratee`'s callback.
+ *
+ * The inverse of [whilst]{@link module:ControlFlow.whilst}.
+ *
+ * @name until
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.whilst]{@link module:ControlFlow.whilst}
+ * @category Control Flow
+ * @param {AsyncFunction} test - asynchronous truth test to perform before each
+ * execution of `iteratee`. Invoked with (callback).
+ * @param {AsyncFunction} iteratee - An async function which is called each time
+ * `test` fails. Invoked with (callback).
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has passed and repeated execution of `iteratee` has stopped. `callback`
+ * will be passed an error and any arguments passed to the final `iteratee`'s
+ * callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if a callback is not passed
+ *
+ * @example
+ * const results = []
+ * let finished = false
+ * async.until(function test(cb) {
+ *     cb(null, finished)
+ * }, function iter(next) {
+ *     fetchPage(url, (err, body) => {
+ *         if (err) return next(err)
+ *         results = results.concat(body.objects)
+ *         finished = !!body.next
+ *         next(err)
+ *     })
+ * }, function done (err) {
+ *     // all pages have been fetched
+ * })
+ */
+function until(test, iteratee, callback) {
+    const _test = wrapAsync(test);
+    return whilst$1((cb) => _test((err, truth) => cb (err, !truth)), iteratee, callback);
+}
+
+/**
+ * Runs the `tasks` array of functions in series, each passing their results to
+ * the next in the array. However, if any of the `tasks` pass an error to their
+ * own callback, the next function is not executed, and the main `callback` is
+ * immediately called with the error.
+ *
+ * @name waterfall
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array} tasks - An array of [async functions]{@link AsyncFunction}
+ * to run.
+ * Each function should complete with any number of `result` values.
+ * The `result` values will be passed as arguments, in order, to the next task.
+ * @param {Function} [callback] - An optional callback to run once all the
+ * functions have completed. This will be passed the results of the last task's
+ * callback. Invoked with (err, [results]).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * async.waterfall([
+ *     function(callback) {
+ *         callback(null, 'one', 'two');
+ *     },
+ *     function(arg1, arg2, callback) {
+ *         // arg1 now equals 'one' and arg2 now equals 'two'
+ *         callback(null, 'three');
+ *     },
+ *     function(arg1, callback) {
+ *         // arg1 now equals 'three'
+ *         callback(null, 'done');
+ *     }
+ * ], function (err, result) {
+ *     // result now equals 'done'
+ * });
+ *
+ * // Or, with named functions:
+ * async.waterfall([
+ *     myFirstFunction,
+ *     mySecondFunction,
+ *     myLastFunction,
+ * ], function (err, result) {
+ *     // result now equals 'done'
+ * });
+ * function myFirstFunction(callback) {
+ *     callback(null, 'one', 'two');
+ * }
+ * function mySecondFunction(arg1, arg2, callback) {
+ *     // arg1 now equals 'one' and arg2 now equals 'two'
+ *     callback(null, 'three');
+ * }
+ * function myLastFunction(arg1, callback) {
+ *     // arg1 now equals 'three'
+ *     callback(null, 'done');
+ * }
+ */
+function waterfall (tasks, callback) {
+    callback = once(callback);
+    if (!Array.isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions'));
+    if (!tasks.length) return callback();
+    var taskIndex = 0;
+
+    function nextTask(args) {
+        var task = wrapAsync(tasks[taskIndex++]);
+        task(...args, onlyOnce(next));
+    }
+
+    function next(err, ...args) {
+        if (err === false) return
+        if (err || taskIndex === tasks.length) {
+            return callback(err, ...args);
+        }
+        nextTask(args);
+    }
+
+    nextTask([]);
+}
+
+var waterfall$1 = awaitify(waterfall);
+
+/**
+ * An "async function" in the context of Async is an asynchronous function with
+ * a variable number of parameters, with the final parameter being a callback.
+ * (`function (arg1, arg2, ..., callback) {}`)
+ * The final callback is of the form `callback(err, results...)`, which must be
+ * called once the function is completed.  The callback should be called with a
+ * Error as its first argument to signal that an error occurred.
+ * Otherwise, if no error occurred, it should be called with `null` as the first
+ * argument, and any additional `result` arguments that may apply, to signal
+ * successful completion.
+ * The callback must be called exactly once, ideally on a later tick of the
+ * JavaScript event loop.
+ *
+ * This type of function is also referred to as a "Node-style async function",
+ * or a "continuation passing-style function" (CPS). Most of the methods of this
+ * library are themselves CPS/Node-style async functions, or functions that
+ * return CPS/Node-style async functions.
+ *
+ * Wherever we accept a Node-style async function, we also directly accept an
+ * [ES2017 `async` function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function}.
+ * In this case, the `async` function will not be passed a final callback
+ * argument, and any thrown error will be used as the `err` argument of the
+ * implicit callback, and the return value will be used as the `result` value.
+ * (i.e. a `rejected` of the returned Promise becomes the `err` callback
+ * argument, and a `resolved` value becomes the `result`.)
+ *
+ * Note, due to JavaScript limitations, we can only detect native `async`
+ * functions and not transpilied implementations.
+ * Your environment must have `async`/`await` support for this to work.
+ * (e.g. Node > v7.6, or a recent version of a modern browser).
+ * If you are using `async` functions through a transpiler (e.g. Babel), you
+ * must still wrap the function with [asyncify]{@link module:Utils.asyncify},
+ * because the `async function` will be compiled to an ordinary function that
+ * returns a promise.
+ *
+ * @typedef {Function} AsyncFunction
+ * @static
+ */
+
+var index = {
+    apply,
+    applyEach: applyEach$1,
+    applyEachSeries,
+    asyncify,
+    auto,
+    autoInject,
+    cargo,
+    cargoQueue: cargo$1,
+    compose,
+    concat: concat$1,
+    concatLimit: concatLimit$1,
+    concatSeries: concatSeries$1,
+    constant,
+    detect: detect$1,
+    detectLimit: detectLimit$1,
+    detectSeries: detectSeries$1,
+    dir,
+    doUntil,
+    doWhilst: doWhilst$1,
+    each,
+    eachLimit: eachLimit$2,
+    eachOf: eachOf$1,
+    eachOfLimit: eachOfLimit$2,
+    eachOfSeries: eachOfSeries$1,
+    eachSeries: eachSeries$1,
+    ensureAsync,
+    every: every$1,
+    everyLimit: everyLimit$1,
+    everySeries: everySeries$1,
+    filter: filter$1,
+    filterLimit: filterLimit$1,
+    filterSeries: filterSeries$1,
+    forever: forever$1,
+    groupBy,
+    groupByLimit: groupByLimit$1,
+    groupBySeries,
+    log,
+    map: map$1,
+    mapLimit: mapLimit$1,
+    mapSeries: mapSeries$1,
+    mapValues,
+    mapValuesLimit: mapValuesLimit$1,
+    mapValuesSeries,
+    memoize,
+    nextTick,
+    parallel: parallel$1,
+    parallelLimit,
+    priorityQueue,
+    queue: queue$1,
+    race: race$1,
+    reduce: reduce$1,
+    reduceRight,
+    reflect,
+    reflectAll,
+    reject: reject$2,
+    rejectLimit: rejectLimit$1,
+    rejectSeries: rejectSeries$1,
+    retry,
+    retryable,
+    seq,
+    series,
+    setImmediate: setImmediate$1,
+    some: some$1,
+    someLimit: someLimit$1,
+    someSeries: someSeries$1,
+    sortBy: sortBy$1,
+    timeout,
+    times,
+    timesLimit,
+    timesSeries,
+    transform,
+    tryEach: tryEach$1,
+    unmemoize,
+    until,
+    waterfall: waterfall$1,
+    whilst: whilst$1,
+
+    // aliases
+    all: every$1,
+    allLimit: everyLimit$1,
+    allSeries: everySeries$1,
+    any: some$1,
+    anyLimit: someLimit$1,
+    anySeries: someSeries$1,
+    find: detect$1,
+    findLimit: detectLimit$1,
+    findSeries: detectSeries$1,
+    flatMap: concat$1,
+    flatMapLimit: concatLimit$1,
+    flatMapSeries: concatSeries$1,
+    forEach: each,
+    forEachSeries: eachSeries$1,
+    forEachLimit: eachLimit$2,
+    forEachOf: eachOf$1,
+    forEachOfSeries: eachOfSeries$1,
+    forEachOfLimit: eachOfLimit$2,
+    inject: reduce$1,
+    foldl: reduce$1,
+    foldr: reduceRight,
+    select: filter$1,
+    selectLimit: filterLimit$1,
+    selectSeries: filterSeries$1,
+    wrapSync: asyncify,
+    during: whilst$1,
+    doDuring: doWhilst$1
+};
+
+export default index;
+export { apply, applyEach$1 as applyEach, applyEachSeries, asyncify, auto, autoInject, cargo, cargo$1 as cargoQueue, compose, concat$1 as concat, concatLimit$1 as concatLimit, concatSeries$1 as concatSeries, constant, detect$1 as detect, detectLimit$1 as detectLimit, detectSeries$1 as detectSeries, dir, doUntil, doWhilst$1 as doWhilst, each, eachLimit$2 as eachLimit, eachOf$1 as eachOf, eachOfLimit$2 as eachOfLimit, eachOfSeries$1 as eachOfSeries, eachSeries$1 as eachSeries, ensureAsync, every$1 as every, everyLimit$1 as everyLimit, everySeries$1 as everySeries, filter$1 as filter, filterLimit$1 as filterLimit, filterSeries$1 as filterSeries, forever$1 as forever, groupBy, groupByLimit$1 as groupByLimit, groupBySeries, log, map$1 as map, mapLimit$1 as mapLimit, mapSeries$1 as mapSeries, mapValues, mapValuesLimit$1 as mapValuesLimit, mapValuesSeries, memoize, nextTick, parallel$1 as parallel, parallelLimit, priorityQueue, queue$1 as queue, race$1 as race, reduce$1 as reduce, reduceRight, reflect, reflectAll, reject$2 as reject, rejectLimit$1 as rejectLimit, rejectSeries$1 as rejectSeries, retry, retryable, seq, series, setImmediate$1 as setImmediate, some$1 as some, someLimit$1 as someLimit, someSeries$1 as someSeries, sortBy$1 as sortBy, timeout, times, timesLimit, timesSeries, transform, tryEach$1 as tryEach, unmemoize, until, waterfall$1 as waterfall, whilst$1 as whilst, every$1 as all, everyLimit$1 as allLimit, everySeries$1 as allSeries, some$1 as any, someLimit$1 as anyLimit, someSeries$1 as anySeries, detect$1 as find, detectLimit$1 as findLimit, detectSeries$1 as findSeries, concat$1 as flatMap, concatLimit$1 as flatMapLimit, concatSeries$1 as flatMapSeries, each as forEach, eachSeries$1 as forEachSeries, eachLimit$2 as forEachLimit, eachOf$1 as forEachOf, eachOfSeries$1 as forEachOfSeries, eachOfLimit$2 as forEachOfLimit, reduce$1 as inject, reduce$1 as foldl, reduceRight as foldr, filter$1 as select, filterLimit$1 as selectLimit, filterSeries$1 as selectSeries, asyncify as wrapSync, whilst$1 as during, doWhilst$1 as doDuring };
diff --git a/node_modules/async/doDuring.js b/node_modules/async/doDuring.js
new file mode 100644
index 0000000000000000000000000000000000000000..4c98e9e1d69ca7361e567129fb1978c8a3402bbb
--- /dev/null
+++ b/node_modules/async/doDuring.js
@@ -0,0 +1,68 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _onlyOnce = require('./internal/onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in
+ * the order of operations, the arguments `test` and `iteratee` are switched.
+ *
+ * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
+ *
+ * @name doWhilst
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.whilst]{@link module:ControlFlow.whilst}
+ * @category Control Flow
+ * @param {AsyncFunction} iteratee - A function which is called each time `test`
+ * passes. Invoked with (callback).
+ * @param {AsyncFunction} test - asynchronous truth test to perform after each
+ * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the
+ * non-error args from the previous callback of `iteratee`.
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has failed and repeated execution of `iteratee` has stopped.
+ * `callback` will be passed an error and any arguments passed to the final
+ * `iteratee`'s callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function doWhilst(iteratee, test, callback) {
+    callback = (0, _onlyOnce2.default)(callback);
+    var _fn = (0, _wrapAsync2.default)(iteratee);
+    var _test = (0, _wrapAsync2.default)(test);
+    var results;
+
+    function next(err, ...args) {
+        if (err) return callback(err);
+        if (err === false) return;
+        results = args;
+        _test(...args, check);
+    }
+
+    function check(err, truth) {
+        if (err) return callback(err);
+        if (err === false) return;
+        if (!truth) return callback(null, ...results);
+        _fn(next);
+    }
+
+    return check(null, true);
+}
+
+exports.default = (0, _awaitify2.default)(doWhilst, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/doUntil.js b/node_modules/async/doUntil.js
new file mode 100644
index 0000000000000000000000000000000000000000..8aa0935040747a92bccbbeb52a150f2f79f1885a
--- /dev/null
+++ b/node_modules/async/doUntil.js
@@ -0,0 +1,46 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = doUntil;
+
+var _doWhilst = require('./doWhilst.js');
+
+var _doWhilst2 = _interopRequireDefault(_doWhilst);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Like ['doWhilst']{@link module:ControlFlow.doWhilst}, except the `test` is inverted. Note the
+ * argument ordering differs from `until`.
+ *
+ * @name doUntil
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.doWhilst]{@link module:ControlFlow.doWhilst}
+ * @category Control Flow
+ * @param {AsyncFunction} iteratee - An async function which is called each time
+ * `test` fails. Invoked with (callback).
+ * @param {AsyncFunction} test - asynchronous truth test to perform after each
+ * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the
+ * non-error args from the previous callback of `iteratee`
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has passed and repeated execution of `iteratee` has stopped. `callback`
+ * will be passed an error and any arguments passed to the final `iteratee`'s
+ * callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function doUntil(iteratee, test, callback) {
+    const _test = (0, _wrapAsync2.default)(test);
+    return (0, _doWhilst2.default)(iteratee, (...args) => {
+        const cb = args.pop();
+        _test(...args, (err, truth) => cb(err, !truth));
+    }, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/doWhilst.js b/node_modules/async/doWhilst.js
new file mode 100644
index 0000000000000000000000000000000000000000..4c98e9e1d69ca7361e567129fb1978c8a3402bbb
--- /dev/null
+++ b/node_modules/async/doWhilst.js
@@ -0,0 +1,68 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _onlyOnce = require('./internal/onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The post-check version of [`whilst`]{@link module:ControlFlow.whilst}. To reflect the difference in
+ * the order of operations, the arguments `test` and `iteratee` are switched.
+ *
+ * `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript.
+ *
+ * @name doWhilst
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.whilst]{@link module:ControlFlow.whilst}
+ * @category Control Flow
+ * @param {AsyncFunction} iteratee - A function which is called each time `test`
+ * passes. Invoked with (callback).
+ * @param {AsyncFunction} test - asynchronous truth test to perform after each
+ * execution of `iteratee`. Invoked with (...args, callback), where `...args` are the
+ * non-error args from the previous callback of `iteratee`.
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has failed and repeated execution of `iteratee` has stopped.
+ * `callback` will be passed an error and any arguments passed to the final
+ * `iteratee`'s callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function doWhilst(iteratee, test, callback) {
+    callback = (0, _onlyOnce2.default)(callback);
+    var _fn = (0, _wrapAsync2.default)(iteratee);
+    var _test = (0, _wrapAsync2.default)(test);
+    var results;
+
+    function next(err, ...args) {
+        if (err) return callback(err);
+        if (err === false) return;
+        results = args;
+        _test(...args, check);
+    }
+
+    function check(err, truth) {
+        if (err) return callback(err);
+        if (err === false) return;
+        if (!truth) return callback(null, ...results);
+        _fn(next);
+    }
+
+    return check(null, true);
+}
+
+exports.default = (0, _awaitify2.default)(doWhilst, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/during.js b/node_modules/async/during.js
new file mode 100644
index 0000000000000000000000000000000000000000..32a47762a518d98e844dcdbda9d1f92aa1106b75
--- /dev/null
+++ b/node_modules/async/during.js
@@ -0,0 +1,78 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _onlyOnce = require('./internal/onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when
+ * stopped, or an error occurs.
+ *
+ * @name whilst
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {AsyncFunction} test - asynchronous truth test to perform before each
+ * execution of `iteratee`. Invoked with ().
+ * @param {AsyncFunction} iteratee - An async function which is called each time
+ * `test` passes. Invoked with (callback).
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has failed and repeated execution of `iteratee` has stopped. `callback`
+ * will be passed an error and any arguments passed to the final `iteratee`'s
+ * callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * var count = 0;
+ * async.whilst(
+ *     function test(cb) { cb(null, count < 5); },
+ *     function iter(callback) {
+ *         count++;
+ *         setTimeout(function() {
+ *             callback(null, count);
+ *         }, 1000);
+ *     },
+ *     function (err, n) {
+ *         // 5 seconds have passed, n = 5
+ *     }
+ * );
+ */
+function whilst(test, iteratee, callback) {
+    callback = (0, _onlyOnce2.default)(callback);
+    var _fn = (0, _wrapAsync2.default)(iteratee);
+    var _test = (0, _wrapAsync2.default)(test);
+    var results = [];
+
+    function next(err, ...rest) {
+        if (err) return callback(err);
+        results = rest;
+        if (err === false) return;
+        _test(check);
+    }
+
+    function check(err, truth) {
+        if (err) return callback(err);
+        if (err === false) return;
+        if (!truth) return callback(null, ...results);
+        _fn(next);
+    }
+
+    return _test(check);
+}
+exports.default = (0, _awaitify2.default)(whilst, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/each.js b/node_modules/async/each.js
new file mode 100644
index 0000000000000000000000000000000000000000..405d495c95e564e4e39c4e30308e7ba5f3b5a713
--- /dev/null
+++ b/node_modules/async/each.js
@@ -0,0 +1,129 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _withoutIndex = require('./internal/withoutIndex.js');
+
+var _withoutIndex2 = _interopRequireDefault(_withoutIndex);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Applies the function `iteratee` to each item in `coll`, in parallel.
+ * The `iteratee` is called with an item from the list, and a callback for when
+ * it has finished. If the `iteratee` passes an error to its `callback`, the
+ * main `callback` (for the `each` function) is immediately called with the
+ * error.
+ *
+ * Note, that since this function applies `iteratee` to each item in parallel,
+ * there is no guarantee that the iteratee functions will complete in order.
+ *
+ * @name each
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias forEach
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to
+ * each item in `coll`. Invoked with (item, callback).
+ * The array index is not passed to the iteratee.
+ * If you need the index, use `eachOf`.
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * const fileList = [ 'dir1/file2.txt', 'dir2/file3.txt', 'dir/file5.txt'];
+ * const withMissingFileList = ['dir1/file1.txt', 'dir4/file2.txt'];
+ *
+ * // asynchronous function that deletes a file
+ * const deleteFile = function(file, callback) {
+ *     fs.unlink(file, callback);
+ * };
+ *
+ * // Using callbacks
+ * async.each(fileList, deleteFile, function(err) {
+ *     if( err ) {
+ *         console.log(err);
+ *     } else {
+ *         console.log('All files have been deleted successfully');
+ *     }
+ * });
+ *
+ * // Error Handling
+ * async.each(withMissingFileList, deleteFile, function(err){
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ *     // since dir4/file2.txt does not exist
+ *     // dir1/file1.txt could have been deleted
+ * });
+ *
+ * // Using Promises
+ * async.each(fileList, deleteFile)
+ * .then( () => {
+ *     console.log('All files have been deleted successfully');
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.each(fileList, deleteFile)
+ * .then( () => {
+ *     console.log('All files have been deleted successfully');
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ *     // since dir4/file2.txt does not exist
+ *     // dir1/file1.txt could have been deleted
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         await async.each(files, deleteFile);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         await async.each(withMissingFileList, deleteFile);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *         // since dir4/file2.txt does not exist
+ *         // dir1/file1.txt could have been deleted
+ *     }
+ * }
+ *
+ */
+function eachLimit(coll, iteratee, callback) {
+  return (0, _eachOf2.default)(coll, (0, _withoutIndex2.default)((0, _wrapAsync2.default)(iteratee)), callback);
+}
+
+exports.default = (0, _awaitify2.default)(eachLimit, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/eachLimit.js b/node_modules/async/eachLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f3d009475a6d5290f51351010f8012ada231b31
--- /dev/null
+++ b/node_modules/async/eachLimit.js
@@ -0,0 +1,50 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _withoutIndex = require('./internal/withoutIndex.js');
+
+var _withoutIndex2 = _interopRequireDefault(_withoutIndex);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name eachLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.each]{@link module:Collections.each}
+ * @alias forEachLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The array index is not passed to the iteratee.
+ * If you need the index, use `eachOfLimit`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachLimit(coll, limit, iteratee, callback) {
+  return (0, _eachOfLimit2.default)(limit)(coll, (0, _withoutIndex2.default)((0, _wrapAsync2.default)(iteratee)), callback);
+}
+exports.default = (0, _awaitify2.default)(eachLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/eachOf.js b/node_modules/async/eachOf.js
new file mode 100644
index 0000000000000000000000000000000000000000..c22614f3013caccf5ba547d0e720d5ab9efe3239
--- /dev/null
+++ b/node_modules/async/eachOf.js
@@ -0,0 +1,185 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _isArrayLike = require('./internal/isArrayLike.js');
+
+var _isArrayLike2 = _interopRequireDefault(_isArrayLike);
+
+var _breakLoop = require('./internal/breakLoop.js');
+
+var _breakLoop2 = _interopRequireDefault(_breakLoop);
+
+var _eachOfLimit = require('./eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _onlyOnce = require('./internal/onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// eachOf implementation optimized for array-likes
+function eachOfArrayLike(coll, iteratee, callback) {
+    callback = (0, _once2.default)(callback);
+    var index = 0,
+        completed = 0,
+        { length } = coll,
+        canceled = false;
+    if (length === 0) {
+        callback(null);
+    }
+
+    function iteratorCallback(err, value) {
+        if (err === false) {
+            canceled = true;
+        }
+        if (canceled === true) return;
+        if (err) {
+            callback(err);
+        } else if (++completed === length || value === _breakLoop2.default) {
+            callback(null);
+        }
+    }
+
+    for (; index < length; index++) {
+        iteratee(coll[index], index, (0, _onlyOnce2.default)(iteratorCallback));
+    }
+}
+
+// a generic version of eachOf which can handle array, object, and iterator cases.
+function eachOfGeneric(coll, iteratee, callback) {
+    return (0, _eachOfLimit2.default)(coll, Infinity, iteratee, callback);
+}
+
+/**
+ * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument
+ * to the iteratee.
+ *
+ * @name eachOf
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias forEachOf
+ * @category Collection
+ * @see [async.each]{@link module:Collections.each}
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each
+ * item in `coll`.
+ * The `key` is the item's key, or index in the case of an array.
+ * Invoked with (item, key, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * // dev.json is a file containing a valid json object config for dev environment
+ * // dev.json is a file containing a valid json object config for test environment
+ * // prod.json is a file containing a valid json object config for prod environment
+ * // invalid.json is a file with a malformed json object
+ *
+ * let configs = {}; //global variable
+ * let validConfigFileMap = {dev: 'dev.json', test: 'test.json', prod: 'prod.json'};
+ * let invalidConfigFileMap = {dev: 'dev.json', test: 'test.json', invalid: 'invalid.json'};
+ *
+ * // asynchronous function that reads a json file and parses the contents as json object
+ * function parseFile(file, key, callback) {
+ *     fs.readFile(file, "utf8", function(err, data) {
+ *         if (err) return calback(err);
+ *         try {
+ *             configs[key] = JSON.parse(data);
+ *         } catch (e) {
+ *             return callback(e);
+ *         }
+ *         callback();
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.forEachOf(validConfigFileMap, parseFile, function (err) {
+ *     if (err) {
+ *         console.error(err);
+ *     } else {
+ *         console.log(configs);
+ *         // configs is now a map of JSON data, e.g.
+ *         // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+ *     }
+ * });
+ *
+ * //Error handing
+ * async.forEachOf(invalidConfigFileMap, parseFile, function (err) {
+ *     if (err) {
+ *         console.error(err);
+ *         // JSON parse error exception
+ *     } else {
+ *         console.log(configs);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.forEachOf(validConfigFileMap, parseFile)
+ * .then( () => {
+ *     console.log(configs);
+ *     // configs is now a map of JSON data, e.g.
+ *     // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+ * }).catch( err => {
+ *     console.error(err);
+ * });
+ *
+ * //Error handing
+ * async.forEachOf(invalidConfigFileMap, parseFile)
+ * .then( () => {
+ *     console.log(configs);
+ * }).catch( err => {
+ *     console.error(err);
+ *     // JSON parse error exception
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.forEachOf(validConfigFileMap, parseFile);
+ *         console.log(configs);
+ *         // configs is now a map of JSON data, e.g.
+ *         // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * //Error handing
+ * async () => {
+ *     try {
+ *         let result = await async.forEachOf(invalidConfigFileMap, parseFile);
+ *         console.log(configs);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // JSON parse error exception
+ *     }
+ * }
+ *
+ */
+function eachOf(coll, iteratee, callback) {
+    var eachOfImplementation = (0, _isArrayLike2.default)(coll) ? eachOfArrayLike : eachOfGeneric;
+    return eachOfImplementation(coll, (0, _wrapAsync2.default)(iteratee), callback);
+}
+
+exports.default = (0, _awaitify2.default)(eachOf, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/eachOfLimit.js b/node_modules/async/eachOfLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..e9fc4db8b875fce8786e6d5cc3a88f7c1661614d
--- /dev/null
+++ b/node_modules/async/eachOfLimit.js
@@ -0,0 +1,47 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachOfLimit2 = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit3 = _interopRequireDefault(_eachOfLimit2);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name eachOfLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.eachOf]{@link module:Collections.eachOf}
+ * @alias forEachOfLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each
+ * item in `coll`. The `key` is the item's key, or index in the case of an
+ * array.
+ * Invoked with (item, key, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachOfLimit(coll, limit, iteratee, callback) {
+  return (0, _eachOfLimit3.default)(limit)(coll, (0, _wrapAsync2.default)(iteratee), callback);
+}
+
+exports.default = (0, _awaitify2.default)(eachOfLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/eachOfSeries.js b/node_modules/async/eachOfSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..cfb0f33c7ea65a07020dad9f8b9fb691494dfe5a
--- /dev/null
+++ b/node_modules/async/eachOfSeries.js
@@ -0,0 +1,39 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachOfLimit = require('./eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time.
+ *
+ * @name eachOfSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.eachOf]{@link module:Collections.eachOf}
+ * @alias forEachOfSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * Invoked with (item, key, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachOfSeries(coll, iteratee, callback) {
+  return (0, _eachOfLimit2.default)(coll, 1, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(eachOfSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/eachSeries.js b/node_modules/async/eachSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..d674d0c3a8caacbab73c9c72698782c494230282
--- /dev/null
+++ b/node_modules/async/eachSeries.js
@@ -0,0 +1,44 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachLimit = require('./eachLimit.js');
+
+var _eachLimit2 = _interopRequireDefault(_eachLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time.
+ *
+ * Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item
+ * in series and therefore the iteratee functions will complete in order.
+
+ * @name eachSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.each]{@link module:Collections.each}
+ * @alias forEachSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each
+ * item in `coll`.
+ * The array index is not passed to the iteratee.
+ * If you need the index, use `eachOfSeries`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachSeries(coll, iteratee, callback) {
+  return (0, _eachLimit2.default)(coll, 1, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(eachSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/ensureAsync.js b/node_modules/async/ensureAsync.js
new file mode 100644
index 0000000000000000000000000000000000000000..ad8beb52b2e24989e1001ffefbdfdf6667dfe082
--- /dev/null
+++ b/node_modules/async/ensureAsync.js
@@ -0,0 +1,67 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = ensureAsync;
+
+var _setImmediate = require('./internal/setImmediate.js');
+
+var _setImmediate2 = _interopRequireDefault(_setImmediate);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Wrap an async function and ensure it calls its callback on a later tick of
+ * the event loop.  If the function already calls its callback on a next tick,
+ * no extra deferral is added. This is useful for preventing stack overflows
+ * (`RangeError: Maximum call stack size exceeded`) and generally keeping
+ * [Zalgo](http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony)
+ * contained. ES2017 `async` functions are returned as-is -- they are immune
+ * to Zalgo's corrupting influences, as they always resolve on a later tick.
+ *
+ * @name ensureAsync
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} fn - an async function, one that expects a node-style
+ * callback as its last argument.
+ * @returns {AsyncFunction} Returns a wrapped function with the exact same call
+ * signature as the function passed in.
+ * @example
+ *
+ * function sometimesAsync(arg, callback) {
+ *     if (cache[arg]) {
+ *         return callback(null, cache[arg]); // this would be synchronous!!
+ *     } else {
+ *         doSomeIO(arg, callback); // this IO would be asynchronous
+ *     }
+ * }
+ *
+ * // this has a risk of stack overflows if many results are cached in a row
+ * async.mapSeries(args, sometimesAsync, done);
+ *
+ * // this will defer sometimesAsync's callback if necessary,
+ * // preventing stack overflows
+ * async.mapSeries(args, async.ensureAsync(sometimesAsync), done);
+ */
+function ensureAsync(fn) {
+    if ((0, _wrapAsync.isAsync)(fn)) return fn;
+    return function (...args /*, callback*/) {
+        var callback = args.pop();
+        var sync = true;
+        args.push((...innerArgs) => {
+            if (sync) {
+                (0, _setImmediate2.default)(() => callback(...innerArgs));
+            } else {
+                callback(...innerArgs);
+            }
+        });
+        fn.apply(this, args);
+        sync = false;
+    };
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/every.js b/node_modules/async/every.js
new file mode 100644
index 0000000000000000000000000000000000000000..148db6836d0f1704ee2dabd5cef96b4ccc177570
--- /dev/null
+++ b/node_modules/async/every.js
@@ -0,0 +1,119 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Returns `true` if every element in `coll` satisfies an async test. If any
+ * iteratee call returns `false`, the main `callback` is immediately called.
+ *
+ * @name every
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias all
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collection in parallel.
+ * The iteratee must complete with a boolean result value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result will be either `true` or `false`
+ * depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file5.txt'];
+ * const withMissingFileList = ['file1.txt','file2.txt','file4.txt'];
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.every(fileList, fileExists, function(err, result) {
+ *     console.log(result);
+ *     // true
+ *     // result is true since every file exists
+ * });
+ *
+ * async.every(withMissingFileList, fileExists, function(err, result) {
+ *     console.log(result);
+ *     // false
+ *     // result is false since NOT every file exists
+ * });
+ *
+ * // Using Promises
+ * async.every(fileList, fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // true
+ *     // result is true since every file exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * async.every(withMissingFileList, fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // false
+ *     // result is false since NOT every file exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.every(fileList, fileExists);
+ *         console.log(result);
+ *         // true
+ *         // result is true since every file exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * async () => {
+ *     try {
+ *         let result = await async.every(withMissingFileList, fileExists);
+ *         console.log(result);
+ *         // false
+ *         // result is false since NOT every file exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function every(coll, iteratee, callback) {
+  return (0, _createTester2.default)(bool => !bool, res => !res)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(every, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/everyLimit.js b/node_modules/async/everyLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..25b2c089cf6f50e7b32194f23df3ef54da1e8289
--- /dev/null
+++ b/node_modules/async/everyLimit.js
@@ -0,0 +1,46 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`every`]{@link module:Collections.every} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name everyLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.every]{@link module:Collections.every}
+ * @alias allLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collection in parallel.
+ * The iteratee must complete with a boolean result value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result will be either `true` or `false`
+ * depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function everyLimit(coll, limit, iteratee, callback) {
+  return (0, _createTester2.default)(bool => !bool, res => !res)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(everyLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/everySeries.js b/node_modules/async/everySeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..147c3dc56fc5b704af935c68bf57fd27e70da1d8
--- /dev/null
+++ b/node_modules/async/everySeries.js
@@ -0,0 +1,45 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`every`]{@link module:Collections.every} but runs only a single async operation at a time.
+ *
+ * @name everySeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.every]{@link module:Collections.every}
+ * @alias allSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collection in series.
+ * The iteratee must complete with a boolean result value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result will be either `true` or `false`
+ * depending on the values of the async tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function everySeries(coll, iteratee, callback) {
+  return (0, _createTester2.default)(bool => !bool, res => !res)(_eachOfSeries2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(everySeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/filter.js b/node_modules/async/filter.js
new file mode 100644
index 0000000000000000000000000000000000000000..303dc1fb92b87c9f8e084e1d2d50a85f18262f88
--- /dev/null
+++ b/node_modules/async/filter.js
@@ -0,0 +1,93 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _filter2 = require('./internal/filter.js');
+
+var _filter3 = _interopRequireDefault(_filter2);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Returns a new array of all the values in `coll` which pass an async truth
+ * test. This operation is performed in parallel, but the results array will be
+ * in the same order as the original.
+ *
+ * @name filter
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias select
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+ * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+ * with a boolean argument once it has completed. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ *
+ * const files = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt'];
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.filter(files, fileExists, function(err, results) {
+ *    if(err) {
+ *        console.log(err);
+ *    } else {
+ *        console.log(results);
+ *        // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+ *        // results is now an array of the existing files
+ *    }
+ * });
+ *
+ * // Using Promises
+ * async.filter(files, fileExists)
+ * .then(results => {
+ *     console.log(results);
+ *     // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+ *     // results is now an array of the existing files
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.filter(files, fileExists);
+ *         console.log(results);
+ *         // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+ *         // results is now an array of the existing files
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function filter(coll, iteratee, callback) {
+  return (0, _filter3.default)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(filter, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/filterLimit.js b/node_modules/async/filterLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..89e55f539ade5fd9744289c0bfbc02fed7e8c79f
--- /dev/null
+++ b/node_modules/async/filterLimit.js
@@ -0,0 +1,45 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _filter2 = require('./internal/filter.js');
+
+var _filter3 = _interopRequireDefault(_filter2);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name filterLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.filter]{@link module:Collections.filter}
+ * @alias selectLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+ * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+ * with a boolean argument once it has completed. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function filterLimit(coll, limit, iteratee, callback) {
+  return (0, _filter3.default)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(filterLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/filterSeries.js b/node_modules/async/filterSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..a045e52c5a4890dd8c326e6c50a5f363192a4aca
--- /dev/null
+++ b/node_modules/async/filterSeries.js
@@ -0,0 +1,43 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _filter2 = require('./internal/filter.js');
+
+var _filter3 = _interopRequireDefault(_filter2);
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time.
+ *
+ * @name filterSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.filter]{@link module:Collections.filter}
+ * @alias selectSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+ * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+ * with a boolean argument once it has completed. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results)
+ * @returns {Promise} a promise, if no callback provided
+ */
+function filterSeries(coll, iteratee, callback) {
+  return (0, _filter3.default)(_eachOfSeries2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(filterSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/find.js b/node_modules/async/find.js
new file mode 100644
index 0000000000000000000000000000000000000000..05b2e5c60fff46fa850597e99992c0094eb8a458
--- /dev/null
+++ b/node_modules/async/find.js
@@ -0,0 +1,96 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Returns the first value in `coll` that passes an async truth test. The
+ * `iteratee` is applied in parallel, meaning the first iteratee to return
+ * `true` will fire the detect `callback` with that result. That means the
+ * result might not be the first item in the original `coll` (in terms of order)
+ * that passes the test.
+
+ * If order within the original `coll` is important, then look at
+ * [`detectSeries`]{@link module:Collections.detectSeries}.
+ *
+ * @name detect
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias find
+ * @category Collections
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+ * The iteratee must complete with a boolean value as its result.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the `iteratee` functions have finished.
+ * Result will be the first item in the array that passes the truth test
+ * (iteratee) or the value `undefined` if none passed. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists,
+ *    function(err, result) {
+ *        console.log(result);
+ *        // dir1/file1.txt
+ *        // result now equals the first file in the list that exists
+ *    }
+ *);
+ *
+ * // Using Promises
+ * async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists)
+ * .then(result => {
+ *     console.log(result);
+ *     // dir1/file1.txt
+ *     // result now equals the first file in the list that exists
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.detect(['file3.txt','file2.txt','dir1/file1.txt'], fileExists);
+ *         console.log(result);
+ *         // dir1/file1.txt
+ *         // result now equals the file in the list that exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function detect(coll, iteratee, callback) {
+  return (0, _createTester2.default)(bool => bool, (res, item) => item)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(detect, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/findLimit.js b/node_modules/async/findLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..db6961ec5e0bd8be5038278b8245af429125b3fb
--- /dev/null
+++ b/node_modules/async/findLimit.js
@@ -0,0 +1,48 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`detect`]{@link module:Collections.detect} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name detectLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.detect]{@link module:Collections.detect}
+ * @alias findLimit
+ * @category Collections
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+ * The iteratee must complete with a boolean value as its result.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the `iteratee` functions have finished.
+ * Result will be the first item in the array that passes the truth test
+ * (iteratee) or the value `undefined` if none passed. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function detectLimit(coll, limit, iteratee, callback) {
+  return (0, _createTester2.default)(bool => bool, (res, item) => item)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(detectLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/findSeries.js b/node_modules/async/findSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..b9131b4a3c5d65c58c0c4743f1845293823787f9
--- /dev/null
+++ b/node_modules/async/findSeries.js
@@ -0,0 +1,47 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`detect`]{@link module:Collections.detect} but runs only a single async operation at a time.
+ *
+ * @name detectSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.detect]{@link module:Collections.detect}
+ * @alias findSeries
+ * @category Collections
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A truth test to apply to each item in `coll`.
+ * The iteratee must complete with a boolean value as its result.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the `iteratee` functions have finished.
+ * Result will be the first item in the array that passes the truth test
+ * (iteratee) or the value `undefined` if none passed. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function detectSeries(coll, iteratee, callback) {
+  return (0, _createTester2.default)(bool => bool, (res, item) => item)((0, _eachOfLimit2.default)(1), coll, iteratee, callback);
+}
+
+exports.default = (0, _awaitify2.default)(detectSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/flatMap.js b/node_modules/async/flatMap.js
new file mode 100644
index 0000000000000000000000000000000000000000..8eed1ac899d83824494757845c34709435327129
--- /dev/null
+++ b/node_modules/async/flatMap.js
@@ -0,0 +1,115 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _concatLimit = require('./concatLimit.js');
+
+var _concatLimit2 = _interopRequireDefault(_concatLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Applies `iteratee` to each item in `coll`, concatenating the results. Returns
+ * the concatenated list. The `iteratee`s are called in parallel, and the
+ * results are concatenated as they return. The results array will be returned in
+ * the original order of `coll` passed to the `iteratee` function.
+ *
+ * @name concat
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @alias flatMap
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
+ * which should use an array as its result. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is an array
+ * containing the concatenated results of the `iteratee` function. Invoked with
+ * (err, results).
+ * @returns A Promise, if no callback is passed
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * let directoryList = ['dir1','dir2','dir3'];
+ * let withMissingDirectoryList = ['dir1','dir2','dir3', 'dir4'];
+ *
+ * // Using callbacks
+ * async.concat(directoryList, fs.readdir, function(err, results) {
+ *    if (err) {
+ *        console.log(err);
+ *    } else {
+ *        console.log(results);
+ *        // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+ *    }
+ * });
+ *
+ * // Error Handling
+ * async.concat(withMissingDirectoryList, fs.readdir, function(err, results) {
+ *    if (err) {
+ *        console.log(err);
+ *        // [ Error: ENOENT: no such file or directory ]
+ *        // since dir4 does not exist
+ *    } else {
+ *        console.log(results);
+ *    }
+ * });
+ *
+ * // Using Promises
+ * async.concat(directoryList, fs.readdir)
+ * .then(results => {
+ *     console.log(results);
+ *     // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+ * }).catch(err => {
+ *      console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.concat(withMissingDirectoryList, fs.readdir)
+ * .then(results => {
+ *     console.log(results);
+ * }).catch(err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ *     // since dir4 does not exist
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.concat(directoryList, fs.readdir);
+ *         console.log(results);
+ *         // [ 'file1.txt', 'file2.txt', 'file3.txt', 'file4.txt', file5.txt ]
+ *     } catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let results = await async.concat(withMissingDirectoryList, fs.readdir);
+ *         console.log(results);
+ *     } catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *         // since dir4 does not exist
+ *     }
+ * }
+ *
+ */
+function concat(coll, iteratee, callback) {
+  return (0, _concatLimit2.default)(coll, Infinity, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(concat, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/flatMapLimit.js b/node_modules/async/flatMapLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..3d170f1770bdb2b8a96ae9928991e6fda027a1f4
--- /dev/null
+++ b/node_modules/async/flatMapLimit.js
@@ -0,0 +1,60 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _mapLimit = require('./mapLimit.js');
+
+var _mapLimit2 = _interopRequireDefault(_mapLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`concat`]{@link module:Collections.concat} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name concatLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.concat]{@link module:Collections.concat}
+ * @category Collection
+ * @alias flatMapLimit
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`,
+ * which should use an array as its result. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is an array
+ * containing the concatenated results of the `iteratee` function. Invoked with
+ * (err, results).
+ * @returns A Promise, if no callback is passed
+ */
+function concatLimit(coll, limit, iteratee, callback) {
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+    return (0, _mapLimit2.default)(coll, limit, (val, iterCb) => {
+        _iteratee(val, (err, ...args) => {
+            if (err) return iterCb(err);
+            return iterCb(err, args);
+        });
+    }, (err, mapResults) => {
+        var result = [];
+        for (var i = 0; i < mapResults.length; i++) {
+            if (mapResults[i]) {
+                result = result.concat(...mapResults[i]);
+            }
+        }
+
+        return callback(err, result);
+    });
+}
+exports.default = (0, _awaitify2.default)(concatLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/flatMapSeries.js b/node_modules/async/flatMapSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..84add3b0651afe444b06cdcb56d8cc1d56c39fb4
--- /dev/null
+++ b/node_modules/async/flatMapSeries.js
@@ -0,0 +1,41 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _concatLimit = require('./concatLimit.js');
+
+var _concatLimit2 = _interopRequireDefault(_concatLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`concat`]{@link module:Collections.concat} but runs only a single async operation at a time.
+ *
+ * @name concatSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.concat]{@link module:Collections.concat}
+ * @category Collection
+ * @alias flatMapSeries
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each item in `coll`.
+ * The iteratee should complete with an array an array of results.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is an array
+ * containing the concatenated results of the `iteratee` function. Invoked with
+ * (err, results).
+ * @returns A Promise, if no callback is passed
+ */
+function concatSeries(coll, iteratee, callback) {
+  return (0, _concatLimit2.default)(coll, 1, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(concatSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/foldl.js b/node_modules/async/foldl.js
new file mode 100644
index 0000000000000000000000000000000000000000..56e2db8139e7ba84cf39981a107b841604673043
--- /dev/null
+++ b/node_modules/async/foldl.js
@@ -0,0 +1,153 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Reduces `coll` into a single value using an async `iteratee` to return each
+ * successive step. `memo` is the initial state of the reduction. This function
+ * only operates in series.
+ *
+ * For performance reasons, it may make sense to split a call to this function
+ * into a parallel map, and then use the normal `Array.prototype.reduce` on the
+ * results. This function is for situations where each step in the reduction
+ * needs to be async; if you can get the data before reducing it, then it's
+ * probably a good idea to do so.
+ *
+ * @name reduce
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias inject
+ * @alias foldl
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {*} memo - The initial state of the reduction.
+ * @param {AsyncFunction} iteratee - A function applied to each item in the
+ * array to produce the next step in the reduction.
+ * The `iteratee` should complete with the next state of the reduction.
+ * If the iteratee completes with an error, the reduction is stopped and the
+ * main `callback` is immediately called with the error.
+ * Invoked with (memo, item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result is the reduced value. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ * // file4.txt does not exist
+ *
+ * const fileList = ['file1.txt','file2.txt','file3.txt'];
+ * const withMissingFileList = ['file1.txt','file2.txt','file3.txt', 'file4.txt'];
+ *
+ * // asynchronous function that computes the file size in bytes
+ * // file size is added to the memoized value, then returned
+ * function getFileSizeInBytes(memo, file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, memo + stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.reduce(fileList, 0, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // 6000
+ *         // which is the sum of the file sizes of the three files
+ *     }
+ * });
+ *
+ * // Error Handling
+ * async.reduce(withMissingFileList, 0, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     } else {
+ *         console.log(result);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.reduce(fileList, 0, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ *     // 6000
+ *     // which is the sum of the file sizes of the three files
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.reduce(withMissingFileList, 0, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.reduce(fileList, 0, getFileSizeInBytes);
+ *         console.log(result);
+ *         // 6000
+ *         // which is the sum of the file sizes of the three files
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes);
+ *         console.log(result);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function reduce(coll, memo, iteratee, callback) {
+    callback = (0, _once2.default)(callback);
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+    return (0, _eachOfSeries2.default)(coll, (x, i, iterCb) => {
+        _iteratee(memo, x, (err, v) => {
+            memo = v;
+            iterCb(err);
+        });
+    }, err => callback(err, memo));
+}
+exports.default = (0, _awaitify2.default)(reduce, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/foldr.js b/node_modules/async/foldr.js
new file mode 100644
index 0000000000000000000000000000000000000000..bee5391d31431a9264ac1a3d435aaee0499941f6
--- /dev/null
+++ b/node_modules/async/foldr.js
@@ -0,0 +1,41 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = reduceRight;
+
+var _reduce = require('./reduce.js');
+
+var _reduce2 = _interopRequireDefault(_reduce);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order.
+ *
+ * @name reduceRight
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.reduce]{@link module:Collections.reduce}
+ * @alias foldr
+ * @category Collection
+ * @param {Array} array - A collection to iterate over.
+ * @param {*} memo - The initial state of the reduction.
+ * @param {AsyncFunction} iteratee - A function applied to each item in the
+ * array to produce the next step in the reduction.
+ * The `iteratee` should complete with the next state of the reduction.
+ * If the iteratee completes with an error, the reduction is stopped and the
+ * main `callback` is immediately called with the error.
+ * Invoked with (memo, item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result is the reduced value. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function reduceRight(array, memo, iteratee, callback) {
+  var reversed = [...array].reverse();
+  return (0, _reduce2.default)(reversed, memo, iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/forEach.js b/node_modules/async/forEach.js
new file mode 100644
index 0000000000000000000000000000000000000000..405d495c95e564e4e39c4e30308e7ba5f3b5a713
--- /dev/null
+++ b/node_modules/async/forEach.js
@@ -0,0 +1,129 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _withoutIndex = require('./internal/withoutIndex.js');
+
+var _withoutIndex2 = _interopRequireDefault(_withoutIndex);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Applies the function `iteratee` to each item in `coll`, in parallel.
+ * The `iteratee` is called with an item from the list, and a callback for when
+ * it has finished. If the `iteratee` passes an error to its `callback`, the
+ * main `callback` (for the `each` function) is immediately called with the
+ * error.
+ *
+ * Note, that since this function applies `iteratee` to each item in parallel,
+ * there is no guarantee that the iteratee functions will complete in order.
+ *
+ * @name each
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias forEach
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to
+ * each item in `coll`. Invoked with (item, callback).
+ * The array index is not passed to the iteratee.
+ * If you need the index, use `eachOf`.
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * const fileList = [ 'dir1/file2.txt', 'dir2/file3.txt', 'dir/file5.txt'];
+ * const withMissingFileList = ['dir1/file1.txt', 'dir4/file2.txt'];
+ *
+ * // asynchronous function that deletes a file
+ * const deleteFile = function(file, callback) {
+ *     fs.unlink(file, callback);
+ * };
+ *
+ * // Using callbacks
+ * async.each(fileList, deleteFile, function(err) {
+ *     if( err ) {
+ *         console.log(err);
+ *     } else {
+ *         console.log('All files have been deleted successfully');
+ *     }
+ * });
+ *
+ * // Error Handling
+ * async.each(withMissingFileList, deleteFile, function(err){
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ *     // since dir4/file2.txt does not exist
+ *     // dir1/file1.txt could have been deleted
+ * });
+ *
+ * // Using Promises
+ * async.each(fileList, deleteFile)
+ * .then( () => {
+ *     console.log('All files have been deleted successfully');
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.each(fileList, deleteFile)
+ * .then( () => {
+ *     console.log('All files have been deleted successfully');
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ *     // since dir4/file2.txt does not exist
+ *     // dir1/file1.txt could have been deleted
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         await async.each(files, deleteFile);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         await async.each(withMissingFileList, deleteFile);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *         // since dir4/file2.txt does not exist
+ *         // dir1/file1.txt could have been deleted
+ *     }
+ * }
+ *
+ */
+function eachLimit(coll, iteratee, callback) {
+  return (0, _eachOf2.default)(coll, (0, _withoutIndex2.default)((0, _wrapAsync2.default)(iteratee)), callback);
+}
+
+exports.default = (0, _awaitify2.default)(eachLimit, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/forEachLimit.js b/node_modules/async/forEachLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f3d009475a6d5290f51351010f8012ada231b31
--- /dev/null
+++ b/node_modules/async/forEachLimit.js
@@ -0,0 +1,50 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _withoutIndex = require('./internal/withoutIndex.js');
+
+var _withoutIndex2 = _interopRequireDefault(_withoutIndex);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`each`]{@link module:Collections.each} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name eachLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.each]{@link module:Collections.each}
+ * @alias forEachLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The array index is not passed to the iteratee.
+ * If you need the index, use `eachOfLimit`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachLimit(coll, limit, iteratee, callback) {
+  return (0, _eachOfLimit2.default)(limit)(coll, (0, _withoutIndex2.default)((0, _wrapAsync2.default)(iteratee)), callback);
+}
+exports.default = (0, _awaitify2.default)(eachLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/forEachOf.js b/node_modules/async/forEachOf.js
new file mode 100644
index 0000000000000000000000000000000000000000..c22614f3013caccf5ba547d0e720d5ab9efe3239
--- /dev/null
+++ b/node_modules/async/forEachOf.js
@@ -0,0 +1,185 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _isArrayLike = require('./internal/isArrayLike.js');
+
+var _isArrayLike2 = _interopRequireDefault(_isArrayLike);
+
+var _breakLoop = require('./internal/breakLoop.js');
+
+var _breakLoop2 = _interopRequireDefault(_breakLoop);
+
+var _eachOfLimit = require('./eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _onlyOnce = require('./internal/onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// eachOf implementation optimized for array-likes
+function eachOfArrayLike(coll, iteratee, callback) {
+    callback = (0, _once2.default)(callback);
+    var index = 0,
+        completed = 0,
+        { length } = coll,
+        canceled = false;
+    if (length === 0) {
+        callback(null);
+    }
+
+    function iteratorCallback(err, value) {
+        if (err === false) {
+            canceled = true;
+        }
+        if (canceled === true) return;
+        if (err) {
+            callback(err);
+        } else if (++completed === length || value === _breakLoop2.default) {
+            callback(null);
+        }
+    }
+
+    for (; index < length; index++) {
+        iteratee(coll[index], index, (0, _onlyOnce2.default)(iteratorCallback));
+    }
+}
+
+// a generic version of eachOf which can handle array, object, and iterator cases.
+function eachOfGeneric(coll, iteratee, callback) {
+    return (0, _eachOfLimit2.default)(coll, Infinity, iteratee, callback);
+}
+
+/**
+ * Like [`each`]{@link module:Collections.each}, except that it passes the key (or index) as the second argument
+ * to the iteratee.
+ *
+ * @name eachOf
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias forEachOf
+ * @category Collection
+ * @see [async.each]{@link module:Collections.each}
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each
+ * item in `coll`.
+ * The `key` is the item's key, or index in the case of an array.
+ * Invoked with (item, key, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * // dev.json is a file containing a valid json object config for dev environment
+ * // dev.json is a file containing a valid json object config for test environment
+ * // prod.json is a file containing a valid json object config for prod environment
+ * // invalid.json is a file with a malformed json object
+ *
+ * let configs = {}; //global variable
+ * let validConfigFileMap = {dev: 'dev.json', test: 'test.json', prod: 'prod.json'};
+ * let invalidConfigFileMap = {dev: 'dev.json', test: 'test.json', invalid: 'invalid.json'};
+ *
+ * // asynchronous function that reads a json file and parses the contents as json object
+ * function parseFile(file, key, callback) {
+ *     fs.readFile(file, "utf8", function(err, data) {
+ *         if (err) return calback(err);
+ *         try {
+ *             configs[key] = JSON.parse(data);
+ *         } catch (e) {
+ *             return callback(e);
+ *         }
+ *         callback();
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.forEachOf(validConfigFileMap, parseFile, function (err) {
+ *     if (err) {
+ *         console.error(err);
+ *     } else {
+ *         console.log(configs);
+ *         // configs is now a map of JSON data, e.g.
+ *         // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+ *     }
+ * });
+ *
+ * //Error handing
+ * async.forEachOf(invalidConfigFileMap, parseFile, function (err) {
+ *     if (err) {
+ *         console.error(err);
+ *         // JSON parse error exception
+ *     } else {
+ *         console.log(configs);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.forEachOf(validConfigFileMap, parseFile)
+ * .then( () => {
+ *     console.log(configs);
+ *     // configs is now a map of JSON data, e.g.
+ *     // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+ * }).catch( err => {
+ *     console.error(err);
+ * });
+ *
+ * //Error handing
+ * async.forEachOf(invalidConfigFileMap, parseFile)
+ * .then( () => {
+ *     console.log(configs);
+ * }).catch( err => {
+ *     console.error(err);
+ *     // JSON parse error exception
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.forEachOf(validConfigFileMap, parseFile);
+ *         console.log(configs);
+ *         // configs is now a map of JSON data, e.g.
+ *         // { dev: //parsed dev.json, test: //parsed test.json, prod: //parsed prod.json}
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * //Error handing
+ * async () => {
+ *     try {
+ *         let result = await async.forEachOf(invalidConfigFileMap, parseFile);
+ *         console.log(configs);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // JSON parse error exception
+ *     }
+ * }
+ *
+ */
+function eachOf(coll, iteratee, callback) {
+    var eachOfImplementation = (0, _isArrayLike2.default)(coll) ? eachOfArrayLike : eachOfGeneric;
+    return eachOfImplementation(coll, (0, _wrapAsync2.default)(iteratee), callback);
+}
+
+exports.default = (0, _awaitify2.default)(eachOf, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/forEachOfLimit.js b/node_modules/async/forEachOfLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..e9fc4db8b875fce8786e6d5cc3a88f7c1661614d
--- /dev/null
+++ b/node_modules/async/forEachOfLimit.js
@@ -0,0 +1,47 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachOfLimit2 = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit3 = _interopRequireDefault(_eachOfLimit2);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`eachOf`]{@link module:Collections.eachOf} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name eachOfLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.eachOf]{@link module:Collections.eachOf}
+ * @alias forEachOfLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each
+ * item in `coll`. The `key` is the item's key, or index in the case of an
+ * array.
+ * Invoked with (item, key, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachOfLimit(coll, limit, iteratee, callback) {
+  return (0, _eachOfLimit3.default)(limit)(coll, (0, _wrapAsync2.default)(iteratee), callback);
+}
+
+exports.default = (0, _awaitify2.default)(eachOfLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/forEachOfSeries.js b/node_modules/async/forEachOfSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..cfb0f33c7ea65a07020dad9f8b9fb691494dfe5a
--- /dev/null
+++ b/node_modules/async/forEachOfSeries.js
@@ -0,0 +1,39 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachOfLimit = require('./eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`eachOf`]{@link module:Collections.eachOf} but runs only a single async operation at a time.
+ *
+ * @name eachOfSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.eachOf]{@link module:Collections.eachOf}
+ * @alias forEachOfSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * Invoked with (item, key, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachOfSeries(coll, iteratee, callback) {
+  return (0, _eachOfLimit2.default)(coll, 1, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(eachOfSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/forEachSeries.js b/node_modules/async/forEachSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..d674d0c3a8caacbab73c9c72698782c494230282
--- /dev/null
+++ b/node_modules/async/forEachSeries.js
@@ -0,0 +1,44 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _eachLimit = require('./eachLimit.js');
+
+var _eachLimit2 = _interopRequireDefault(_eachLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`each`]{@link module:Collections.each} but runs only a single async operation at a time.
+ *
+ * Note, that unlike [`each`]{@link module:Collections.each}, this function applies iteratee to each item
+ * in series and therefore the iteratee functions will complete in order.
+
+ * @name eachSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.each]{@link module:Collections.each}
+ * @alias forEachSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each
+ * item in `coll`.
+ * The array index is not passed to the iteratee.
+ * If you need the index, use `eachOfSeries`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all
+ * `iteratee` functions have finished, or an error occurs. Invoked with (err).
+ * @returns {Promise} a promise, if a callback is omitted
+ */
+function eachSeries(coll, iteratee, callback) {
+  return (0, _eachLimit2.default)(coll, 1, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(eachSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/forever.js b/node_modules/async/forever.js
new file mode 100644
index 0000000000000000000000000000000000000000..2c8d5b8f29ba7ee80a565670facf944bec930265
--- /dev/null
+++ b/node_modules/async/forever.js
@@ -0,0 +1,68 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _onlyOnce = require('./internal/onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _ensureAsync = require('./ensureAsync.js');
+
+var _ensureAsync2 = _interopRequireDefault(_ensureAsync);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Calls the asynchronous function `fn` with a callback parameter that allows it
+ * to call itself again, in series, indefinitely.
+
+ * If an error is passed to the callback then `errback` is called with the
+ * error, and execution stops, otherwise it will never be called.
+ *
+ * @name forever
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {AsyncFunction} fn - an async function to call repeatedly.
+ * Invoked with (next).
+ * @param {Function} [errback] - when `fn` passes an error to it's callback,
+ * this function will be called, and execution stops. Invoked with (err).
+ * @returns {Promise} a promise that rejects if an error occurs and an errback
+ * is not passed
+ * @example
+ *
+ * async.forever(
+ *     function(next) {
+ *         // next is suitable for passing to things that need a callback(err [, whatever]);
+ *         // it will result in this function being called again.
+ *     },
+ *     function(err) {
+ *         // if next is called with a value in its first parameter, it will appear
+ *         // in here as 'err', and execution will stop.
+ *     }
+ * );
+ */
+function forever(fn, errback) {
+    var done = (0, _onlyOnce2.default)(errback);
+    var task = (0, _wrapAsync2.default)((0, _ensureAsync2.default)(fn));
+
+    function next(err) {
+        if (err) return done(err);
+        if (err === false) return;
+        task(next);
+    }
+    return next();
+}
+exports.default = (0, _awaitify2.default)(forever, 2);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/groupBy.js b/node_modules/async/groupBy.js
new file mode 100644
index 0000000000000000000000000000000000000000..6bb52aaa6d0b8267c1dd815c47c8a8cec8433a03
--- /dev/null
+++ b/node_modules/async/groupBy.js
@@ -0,0 +1,108 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = groupBy;
+
+var _groupByLimit = require('./groupByLimit.js');
+
+var _groupByLimit2 = _interopRequireDefault(_groupByLimit);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Returns a new object, where each value corresponds to an array of items, from
+ * `coll`, that returned the corresponding key. That is, the keys of the object
+ * correspond to the values passed to the `iteratee` callback.
+ *
+ * Note: Since this function applies the `iteratee` to each item in parallel,
+ * there is no guarantee that the `iteratee` functions will complete in order.
+ * However, the values for each key in the `result` will be in the same order as
+ * the original `coll`. For Objects, the values will roughly be in the order of
+ * the original Objects' keys (but this can vary across JavaScript engines).
+ *
+ * @name groupBy
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with a `key` to group the value under.
+ * Invoked with (value, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Result is an `Object` whoses
+ * properties are arrays of values which returned the corresponding key.
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * const files = ['dir1/file1.txt','dir2','dir4']
+ *
+ * // asynchronous function that detects file type as none, file, or directory
+ * function detectFile(file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(null, 'none');
+ *         }
+ *         callback(null, stat.isDirectory() ? 'directory' : 'file');
+ *     });
+ * }
+ *
+ * //Using callbacks
+ * async.groupBy(files, detectFile, function(err, result) {
+ *     if(err) {
+ *         console.log(err);
+ *     } else {
+ *	       console.log(result);
+ *         // {
+ *         //     file: [ 'dir1/file1.txt' ],
+ *         //     none: [ 'dir4' ],
+ *         //     directory: [ 'dir2']
+ *         // }
+ *         // result is object containing the files grouped by type
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.groupBy(files, detectFile)
+ * .then( result => {
+ *     console.log(result);
+ *     // {
+ *     //     file: [ 'dir1/file1.txt' ],
+ *     //     none: [ 'dir4' ],
+ *     //     directory: [ 'dir2']
+ *     // }
+ *     // result is object containing the files grouped by type
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.groupBy(files, detectFile);
+ *         console.log(result);
+ *         // {
+ *         //     file: [ 'dir1/file1.txt' ],
+ *         //     none: [ 'dir4' ],
+ *         //     directory: [ 'dir2']
+ *         // }
+ *         // result is object containing the files grouped by type
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function groupBy(coll, iteratee, callback) {
+  return (0, _groupByLimit2.default)(coll, Infinity, iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/groupByLimit.js b/node_modules/async/groupByLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..5766d6e0b62953f48a4d263316d0fd94a6a6a84a
--- /dev/null
+++ b/node_modules/async/groupByLimit.js
@@ -0,0 +1,71 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _mapLimit = require('./mapLimit.js');
+
+var _mapLimit2 = _interopRequireDefault(_mapLimit);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`groupBy`]{@link module:Collections.groupBy} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name groupByLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.groupBy]{@link module:Collections.groupBy}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with a `key` to group the value under.
+ * Invoked with (value, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Result is an `Object` whoses
+ * properties are arrays of values which returned the corresponding key.
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function groupByLimit(coll, limit, iteratee, callback) {
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+    return (0, _mapLimit2.default)(coll, limit, (val, iterCb) => {
+        _iteratee(val, (err, key) => {
+            if (err) return iterCb(err);
+            return iterCb(err, { key, val });
+        });
+    }, (err, mapResults) => {
+        var result = {};
+        // from MDN, handle object having an `hasOwnProperty` prop
+        var { hasOwnProperty } = Object.prototype;
+
+        for (var i = 0; i < mapResults.length; i++) {
+            if (mapResults[i]) {
+                var { key } = mapResults[i];
+                var { val } = mapResults[i];
+
+                if (hasOwnProperty.call(result, key)) {
+                    result[key].push(val);
+                } else {
+                    result[key] = [val];
+                }
+            }
+        }
+
+        return callback(err, result);
+    });
+}
+
+exports.default = (0, _awaitify2.default)(groupByLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/groupBySeries.js b/node_modules/async/groupBySeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..6056743531485946a548d7c0c97679f488cd3e8d
--- /dev/null
+++ b/node_modules/async/groupBySeries.js
@@ -0,0 +1,36 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = groupBySeries;
+
+var _groupByLimit = require('./groupByLimit.js');
+
+var _groupByLimit2 = _interopRequireDefault(_groupByLimit);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`groupBy`]{@link module:Collections.groupBy} but runs only a single async operation at a time.
+ *
+ * @name groupBySeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.groupBy]{@link module:Collections.groupBy}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with a `key` to group the value under.
+ * Invoked with (value, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Result is an `Object` whose
+ * properties are arrays of values which returned the corresponding key.
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function groupBySeries(coll, iteratee, callback) {
+  return (0, _groupByLimit2.default)(coll, 1, iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/index.js b/node_modules/async/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..ce647d5997547c112395afdac004aefeb746fc4c
--- /dev/null
+++ b/node_modules/async/index.js
@@ -0,0 +1,588 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.doDuring = exports.during = exports.wrapSync = undefined;
+exports.selectSeries = exports.selectLimit = exports.select = exports.foldr = exports.foldl = exports.inject = exports.forEachOfLimit = exports.forEachOfSeries = exports.forEachOf = exports.forEachLimit = exports.forEachSeries = exports.forEach = exports.flatMapSeries = exports.flatMapLimit = exports.flatMap = exports.findSeries = exports.findLimit = exports.find = exports.anySeries = exports.anyLimit = exports.any = exports.allSeries = exports.allLimit = exports.all = exports.whilst = exports.waterfall = exports.until = exports.unmemoize = exports.tryEach = exports.transform = exports.timesSeries = exports.timesLimit = exports.times = exports.timeout = exports.sortBy = exports.someSeries = exports.someLimit = exports.some = exports.setImmediate = exports.series = exports.seq = exports.retryable = exports.retry = exports.rejectSeries = exports.rejectLimit = exports.reject = exports.reflectAll = exports.reflect = exports.reduceRight = exports.reduce = exports.race = exports.queue = exports.priorityQueue = exports.parallelLimit = exports.parallel = exports.nextTick = exports.memoize = exports.mapValuesSeries = exports.mapValuesLimit = exports.mapValues = exports.mapSeries = exports.mapLimit = exports.map = exports.log = exports.groupBySeries = exports.groupByLimit = exports.groupBy = exports.forever = exports.filterSeries = exports.filterLimit = exports.filter = exports.everySeries = exports.everyLimit = exports.every = exports.ensureAsync = exports.eachSeries = exports.eachOfSeries = exports.eachOfLimit = exports.eachOf = exports.eachLimit = exports.each = exports.doWhilst = exports.doUntil = exports.dir = exports.detectSeries = exports.detectLimit = exports.detect = exports.constant = exports.concatSeries = exports.concatLimit = exports.concat = exports.compose = exports.cargoQueue = exports.cargo = exports.autoInject = exports.auto = exports.asyncify = exports.applyEachSeries = exports.applyEach = exports.apply = undefined;
+
+var _apply = require('./apply');
+
+var _apply2 = _interopRequireDefault(_apply);
+
+var _applyEach = require('./applyEach');
+
+var _applyEach2 = _interopRequireDefault(_applyEach);
+
+var _applyEachSeries = require('./applyEachSeries');
+
+var _applyEachSeries2 = _interopRequireDefault(_applyEachSeries);
+
+var _asyncify = require('./asyncify');
+
+var _asyncify2 = _interopRequireDefault(_asyncify);
+
+var _auto = require('./auto');
+
+var _auto2 = _interopRequireDefault(_auto);
+
+var _autoInject = require('./autoInject');
+
+var _autoInject2 = _interopRequireDefault(_autoInject);
+
+var _cargo = require('./cargo');
+
+var _cargo2 = _interopRequireDefault(_cargo);
+
+var _cargoQueue = require('./cargoQueue');
+
+var _cargoQueue2 = _interopRequireDefault(_cargoQueue);
+
+var _compose = require('./compose');
+
+var _compose2 = _interopRequireDefault(_compose);
+
+var _concat = require('./concat');
+
+var _concat2 = _interopRequireDefault(_concat);
+
+var _concatLimit = require('./concatLimit');
+
+var _concatLimit2 = _interopRequireDefault(_concatLimit);
+
+var _concatSeries = require('./concatSeries');
+
+var _concatSeries2 = _interopRequireDefault(_concatSeries);
+
+var _constant = require('./constant');
+
+var _constant2 = _interopRequireDefault(_constant);
+
+var _detect = require('./detect');
+
+var _detect2 = _interopRequireDefault(_detect);
+
+var _detectLimit = require('./detectLimit');
+
+var _detectLimit2 = _interopRequireDefault(_detectLimit);
+
+var _detectSeries = require('./detectSeries');
+
+var _detectSeries2 = _interopRequireDefault(_detectSeries);
+
+var _dir = require('./dir');
+
+var _dir2 = _interopRequireDefault(_dir);
+
+var _doUntil = require('./doUntil');
+
+var _doUntil2 = _interopRequireDefault(_doUntil);
+
+var _doWhilst = require('./doWhilst');
+
+var _doWhilst2 = _interopRequireDefault(_doWhilst);
+
+var _each = require('./each');
+
+var _each2 = _interopRequireDefault(_each);
+
+var _eachLimit = require('./eachLimit');
+
+var _eachLimit2 = _interopRequireDefault(_eachLimit);
+
+var _eachOf = require('./eachOf');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _eachOfLimit = require('./eachOfLimit');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _eachOfSeries = require('./eachOfSeries');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _eachSeries = require('./eachSeries');
+
+var _eachSeries2 = _interopRequireDefault(_eachSeries);
+
+var _ensureAsync = require('./ensureAsync');
+
+var _ensureAsync2 = _interopRequireDefault(_ensureAsync);
+
+var _every = require('./every');
+
+var _every2 = _interopRequireDefault(_every);
+
+var _everyLimit = require('./everyLimit');
+
+var _everyLimit2 = _interopRequireDefault(_everyLimit);
+
+var _everySeries = require('./everySeries');
+
+var _everySeries2 = _interopRequireDefault(_everySeries);
+
+var _filter = require('./filter');
+
+var _filter2 = _interopRequireDefault(_filter);
+
+var _filterLimit = require('./filterLimit');
+
+var _filterLimit2 = _interopRequireDefault(_filterLimit);
+
+var _filterSeries = require('./filterSeries');
+
+var _filterSeries2 = _interopRequireDefault(_filterSeries);
+
+var _forever = require('./forever');
+
+var _forever2 = _interopRequireDefault(_forever);
+
+var _groupBy = require('./groupBy');
+
+var _groupBy2 = _interopRequireDefault(_groupBy);
+
+var _groupByLimit = require('./groupByLimit');
+
+var _groupByLimit2 = _interopRequireDefault(_groupByLimit);
+
+var _groupBySeries = require('./groupBySeries');
+
+var _groupBySeries2 = _interopRequireDefault(_groupBySeries);
+
+var _log = require('./log');
+
+var _log2 = _interopRequireDefault(_log);
+
+var _map = require('./map');
+
+var _map2 = _interopRequireDefault(_map);
+
+var _mapLimit = require('./mapLimit');
+
+var _mapLimit2 = _interopRequireDefault(_mapLimit);
+
+var _mapSeries = require('./mapSeries');
+
+var _mapSeries2 = _interopRequireDefault(_mapSeries);
+
+var _mapValues = require('./mapValues');
+
+var _mapValues2 = _interopRequireDefault(_mapValues);
+
+var _mapValuesLimit = require('./mapValuesLimit');
+
+var _mapValuesLimit2 = _interopRequireDefault(_mapValuesLimit);
+
+var _mapValuesSeries = require('./mapValuesSeries');
+
+var _mapValuesSeries2 = _interopRequireDefault(_mapValuesSeries);
+
+var _memoize = require('./memoize');
+
+var _memoize2 = _interopRequireDefault(_memoize);
+
+var _nextTick = require('./nextTick');
+
+var _nextTick2 = _interopRequireDefault(_nextTick);
+
+var _parallel = require('./parallel');
+
+var _parallel2 = _interopRequireDefault(_parallel);
+
+var _parallelLimit = require('./parallelLimit');
+
+var _parallelLimit2 = _interopRequireDefault(_parallelLimit);
+
+var _priorityQueue = require('./priorityQueue');
+
+var _priorityQueue2 = _interopRequireDefault(_priorityQueue);
+
+var _queue = require('./queue');
+
+var _queue2 = _interopRequireDefault(_queue);
+
+var _race = require('./race');
+
+var _race2 = _interopRequireDefault(_race);
+
+var _reduce = require('./reduce');
+
+var _reduce2 = _interopRequireDefault(_reduce);
+
+var _reduceRight = require('./reduceRight');
+
+var _reduceRight2 = _interopRequireDefault(_reduceRight);
+
+var _reflect = require('./reflect');
+
+var _reflect2 = _interopRequireDefault(_reflect);
+
+var _reflectAll = require('./reflectAll');
+
+var _reflectAll2 = _interopRequireDefault(_reflectAll);
+
+var _reject = require('./reject');
+
+var _reject2 = _interopRequireDefault(_reject);
+
+var _rejectLimit = require('./rejectLimit');
+
+var _rejectLimit2 = _interopRequireDefault(_rejectLimit);
+
+var _rejectSeries = require('./rejectSeries');
+
+var _rejectSeries2 = _interopRequireDefault(_rejectSeries);
+
+var _retry = require('./retry');
+
+var _retry2 = _interopRequireDefault(_retry);
+
+var _retryable = require('./retryable');
+
+var _retryable2 = _interopRequireDefault(_retryable);
+
+var _seq = require('./seq');
+
+var _seq2 = _interopRequireDefault(_seq);
+
+var _series = require('./series');
+
+var _series2 = _interopRequireDefault(_series);
+
+var _setImmediate = require('./setImmediate');
+
+var _setImmediate2 = _interopRequireDefault(_setImmediate);
+
+var _some = require('./some');
+
+var _some2 = _interopRequireDefault(_some);
+
+var _someLimit = require('./someLimit');
+
+var _someLimit2 = _interopRequireDefault(_someLimit);
+
+var _someSeries = require('./someSeries');
+
+var _someSeries2 = _interopRequireDefault(_someSeries);
+
+var _sortBy = require('./sortBy');
+
+var _sortBy2 = _interopRequireDefault(_sortBy);
+
+var _timeout = require('./timeout');
+
+var _timeout2 = _interopRequireDefault(_timeout);
+
+var _times = require('./times');
+
+var _times2 = _interopRequireDefault(_times);
+
+var _timesLimit = require('./timesLimit');
+
+var _timesLimit2 = _interopRequireDefault(_timesLimit);
+
+var _timesSeries = require('./timesSeries');
+
+var _timesSeries2 = _interopRequireDefault(_timesSeries);
+
+var _transform = require('./transform');
+
+var _transform2 = _interopRequireDefault(_transform);
+
+var _tryEach = require('./tryEach');
+
+var _tryEach2 = _interopRequireDefault(_tryEach);
+
+var _unmemoize = require('./unmemoize');
+
+var _unmemoize2 = _interopRequireDefault(_unmemoize);
+
+var _until = require('./until');
+
+var _until2 = _interopRequireDefault(_until);
+
+var _waterfall = require('./waterfall');
+
+var _waterfall2 = _interopRequireDefault(_waterfall);
+
+var _whilst = require('./whilst');
+
+var _whilst2 = _interopRequireDefault(_whilst);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * An "async function" in the context of Async is an asynchronous function with
+ * a variable number of parameters, with the final parameter being a callback.
+ * (`function (arg1, arg2, ..., callback) {}`)
+ * The final callback is of the form `callback(err, results...)`, which must be
+ * called once the function is completed.  The callback should be called with a
+ * Error as its first argument to signal that an error occurred.
+ * Otherwise, if no error occurred, it should be called with `null` as the first
+ * argument, and any additional `result` arguments that may apply, to signal
+ * successful completion.
+ * The callback must be called exactly once, ideally on a later tick of the
+ * JavaScript event loop.
+ *
+ * This type of function is also referred to as a "Node-style async function",
+ * or a "continuation passing-style function" (CPS). Most of the methods of this
+ * library are themselves CPS/Node-style async functions, or functions that
+ * return CPS/Node-style async functions.
+ *
+ * Wherever we accept a Node-style async function, we also directly accept an
+ * [ES2017 `async` function]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function}.
+ * In this case, the `async` function will not be passed a final callback
+ * argument, and any thrown error will be used as the `err` argument of the
+ * implicit callback, and the return value will be used as the `result` value.
+ * (i.e. a `rejected` of the returned Promise becomes the `err` callback
+ * argument, and a `resolved` value becomes the `result`.)
+ *
+ * Note, due to JavaScript limitations, we can only detect native `async`
+ * functions and not transpilied implementations.
+ * Your environment must have `async`/`await` support for this to work.
+ * (e.g. Node > v7.6, or a recent version of a modern browser).
+ * If you are using `async` functions through a transpiler (e.g. Babel), you
+ * must still wrap the function with [asyncify]{@link module:Utils.asyncify},
+ * because the `async function` will be compiled to an ordinary function that
+ * returns a promise.
+ *
+ * @typedef {Function} AsyncFunction
+ * @static
+ */
+
+/**
+ * Async is a utility module which provides straight-forward, powerful functions
+ * for working with asynchronous JavaScript. Although originally designed for
+ * use with [Node.js](http://nodejs.org) and installable via
+ * `npm install --save async`, it can also be used directly in the browser.
+ * @module async
+ * @see AsyncFunction
+ */
+
+/**
+ * A collection of `async` functions for manipulating collections, such as
+ * arrays and objects.
+ * @module Collections
+ */
+
+/**
+ * A collection of `async` functions for controlling the flow through a script.
+ * @module ControlFlow
+ */
+
+/**
+ * A collection of `async` utility functions.
+ * @module Utils
+ */
+
+exports.default = {
+  apply: _apply2.default,
+  applyEach: _applyEach2.default,
+  applyEachSeries: _applyEachSeries2.default,
+  asyncify: _asyncify2.default,
+  auto: _auto2.default,
+  autoInject: _autoInject2.default,
+  cargo: _cargo2.default,
+  cargoQueue: _cargoQueue2.default,
+  compose: _compose2.default,
+  concat: _concat2.default,
+  concatLimit: _concatLimit2.default,
+  concatSeries: _concatSeries2.default,
+  constant: _constant2.default,
+  detect: _detect2.default,
+  detectLimit: _detectLimit2.default,
+  detectSeries: _detectSeries2.default,
+  dir: _dir2.default,
+  doUntil: _doUntil2.default,
+  doWhilst: _doWhilst2.default,
+  each: _each2.default,
+  eachLimit: _eachLimit2.default,
+  eachOf: _eachOf2.default,
+  eachOfLimit: _eachOfLimit2.default,
+  eachOfSeries: _eachOfSeries2.default,
+  eachSeries: _eachSeries2.default,
+  ensureAsync: _ensureAsync2.default,
+  every: _every2.default,
+  everyLimit: _everyLimit2.default,
+  everySeries: _everySeries2.default,
+  filter: _filter2.default,
+  filterLimit: _filterLimit2.default,
+  filterSeries: _filterSeries2.default,
+  forever: _forever2.default,
+  groupBy: _groupBy2.default,
+  groupByLimit: _groupByLimit2.default,
+  groupBySeries: _groupBySeries2.default,
+  log: _log2.default,
+  map: _map2.default,
+  mapLimit: _mapLimit2.default,
+  mapSeries: _mapSeries2.default,
+  mapValues: _mapValues2.default,
+  mapValuesLimit: _mapValuesLimit2.default,
+  mapValuesSeries: _mapValuesSeries2.default,
+  memoize: _memoize2.default,
+  nextTick: _nextTick2.default,
+  parallel: _parallel2.default,
+  parallelLimit: _parallelLimit2.default,
+  priorityQueue: _priorityQueue2.default,
+  queue: _queue2.default,
+  race: _race2.default,
+  reduce: _reduce2.default,
+  reduceRight: _reduceRight2.default,
+  reflect: _reflect2.default,
+  reflectAll: _reflectAll2.default,
+  reject: _reject2.default,
+  rejectLimit: _rejectLimit2.default,
+  rejectSeries: _rejectSeries2.default,
+  retry: _retry2.default,
+  retryable: _retryable2.default,
+  seq: _seq2.default,
+  series: _series2.default,
+  setImmediate: _setImmediate2.default,
+  some: _some2.default,
+  someLimit: _someLimit2.default,
+  someSeries: _someSeries2.default,
+  sortBy: _sortBy2.default,
+  timeout: _timeout2.default,
+  times: _times2.default,
+  timesLimit: _timesLimit2.default,
+  timesSeries: _timesSeries2.default,
+  transform: _transform2.default,
+  tryEach: _tryEach2.default,
+  unmemoize: _unmemoize2.default,
+  until: _until2.default,
+  waterfall: _waterfall2.default,
+  whilst: _whilst2.default,
+
+  // aliases
+  all: _every2.default,
+  allLimit: _everyLimit2.default,
+  allSeries: _everySeries2.default,
+  any: _some2.default,
+  anyLimit: _someLimit2.default,
+  anySeries: _someSeries2.default,
+  find: _detect2.default,
+  findLimit: _detectLimit2.default,
+  findSeries: _detectSeries2.default,
+  flatMap: _concat2.default,
+  flatMapLimit: _concatLimit2.default,
+  flatMapSeries: _concatSeries2.default,
+  forEach: _each2.default,
+  forEachSeries: _eachSeries2.default,
+  forEachLimit: _eachLimit2.default,
+  forEachOf: _eachOf2.default,
+  forEachOfSeries: _eachOfSeries2.default,
+  forEachOfLimit: _eachOfLimit2.default,
+  inject: _reduce2.default,
+  foldl: _reduce2.default,
+  foldr: _reduceRight2.default,
+  select: _filter2.default,
+  selectLimit: _filterLimit2.default,
+  selectSeries: _filterSeries2.default,
+  wrapSync: _asyncify2.default,
+  during: _whilst2.default,
+  doDuring: _doWhilst2.default
+};
+exports.apply = _apply2.default;
+exports.applyEach = _applyEach2.default;
+exports.applyEachSeries = _applyEachSeries2.default;
+exports.asyncify = _asyncify2.default;
+exports.auto = _auto2.default;
+exports.autoInject = _autoInject2.default;
+exports.cargo = _cargo2.default;
+exports.cargoQueue = _cargoQueue2.default;
+exports.compose = _compose2.default;
+exports.concat = _concat2.default;
+exports.concatLimit = _concatLimit2.default;
+exports.concatSeries = _concatSeries2.default;
+exports.constant = _constant2.default;
+exports.detect = _detect2.default;
+exports.detectLimit = _detectLimit2.default;
+exports.detectSeries = _detectSeries2.default;
+exports.dir = _dir2.default;
+exports.doUntil = _doUntil2.default;
+exports.doWhilst = _doWhilst2.default;
+exports.each = _each2.default;
+exports.eachLimit = _eachLimit2.default;
+exports.eachOf = _eachOf2.default;
+exports.eachOfLimit = _eachOfLimit2.default;
+exports.eachOfSeries = _eachOfSeries2.default;
+exports.eachSeries = _eachSeries2.default;
+exports.ensureAsync = _ensureAsync2.default;
+exports.every = _every2.default;
+exports.everyLimit = _everyLimit2.default;
+exports.everySeries = _everySeries2.default;
+exports.filter = _filter2.default;
+exports.filterLimit = _filterLimit2.default;
+exports.filterSeries = _filterSeries2.default;
+exports.forever = _forever2.default;
+exports.groupBy = _groupBy2.default;
+exports.groupByLimit = _groupByLimit2.default;
+exports.groupBySeries = _groupBySeries2.default;
+exports.log = _log2.default;
+exports.map = _map2.default;
+exports.mapLimit = _mapLimit2.default;
+exports.mapSeries = _mapSeries2.default;
+exports.mapValues = _mapValues2.default;
+exports.mapValuesLimit = _mapValuesLimit2.default;
+exports.mapValuesSeries = _mapValuesSeries2.default;
+exports.memoize = _memoize2.default;
+exports.nextTick = _nextTick2.default;
+exports.parallel = _parallel2.default;
+exports.parallelLimit = _parallelLimit2.default;
+exports.priorityQueue = _priorityQueue2.default;
+exports.queue = _queue2.default;
+exports.race = _race2.default;
+exports.reduce = _reduce2.default;
+exports.reduceRight = _reduceRight2.default;
+exports.reflect = _reflect2.default;
+exports.reflectAll = _reflectAll2.default;
+exports.reject = _reject2.default;
+exports.rejectLimit = _rejectLimit2.default;
+exports.rejectSeries = _rejectSeries2.default;
+exports.retry = _retry2.default;
+exports.retryable = _retryable2.default;
+exports.seq = _seq2.default;
+exports.series = _series2.default;
+exports.setImmediate = _setImmediate2.default;
+exports.some = _some2.default;
+exports.someLimit = _someLimit2.default;
+exports.someSeries = _someSeries2.default;
+exports.sortBy = _sortBy2.default;
+exports.timeout = _timeout2.default;
+exports.times = _times2.default;
+exports.timesLimit = _timesLimit2.default;
+exports.timesSeries = _timesSeries2.default;
+exports.transform = _transform2.default;
+exports.tryEach = _tryEach2.default;
+exports.unmemoize = _unmemoize2.default;
+exports.until = _until2.default;
+exports.waterfall = _waterfall2.default;
+exports.whilst = _whilst2.default;
+exports.all = _every2.default;
+exports.allLimit = _everyLimit2.default;
+exports.allSeries = _everySeries2.default;
+exports.any = _some2.default;
+exports.anyLimit = _someLimit2.default;
+exports.anySeries = _someSeries2.default;
+exports.find = _detect2.default;
+exports.findLimit = _detectLimit2.default;
+exports.findSeries = _detectSeries2.default;
+exports.flatMap = _concat2.default;
+exports.flatMapLimit = _concatLimit2.default;
+exports.flatMapSeries = _concatSeries2.default;
+exports.forEach = _each2.default;
+exports.forEachSeries = _eachSeries2.default;
+exports.forEachLimit = _eachLimit2.default;
+exports.forEachOf = _eachOf2.default;
+exports.forEachOfSeries = _eachOfSeries2.default;
+exports.forEachOfLimit = _eachOfLimit2.default;
+exports.inject = _reduce2.default;
+exports.foldl = _reduce2.default;
+exports.foldr = _reduceRight2.default;
+exports.select = _filter2.default;
+exports.selectLimit = _filterLimit2.default;
+exports.selectSeries = _filterSeries2.default;
+exports.wrapSync = _asyncify2.default;
+exports.during = _whilst2.default;
+exports.doDuring = _doWhilst2.default;
\ No newline at end of file
diff --git a/node_modules/async/inject.js b/node_modules/async/inject.js
new file mode 100644
index 0000000000000000000000000000000000000000..56e2db8139e7ba84cf39981a107b841604673043
--- /dev/null
+++ b/node_modules/async/inject.js
@@ -0,0 +1,153 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Reduces `coll` into a single value using an async `iteratee` to return each
+ * successive step. `memo` is the initial state of the reduction. This function
+ * only operates in series.
+ *
+ * For performance reasons, it may make sense to split a call to this function
+ * into a parallel map, and then use the normal `Array.prototype.reduce` on the
+ * results. This function is for situations where each step in the reduction
+ * needs to be async; if you can get the data before reducing it, then it's
+ * probably a good idea to do so.
+ *
+ * @name reduce
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias inject
+ * @alias foldl
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {*} memo - The initial state of the reduction.
+ * @param {AsyncFunction} iteratee - A function applied to each item in the
+ * array to produce the next step in the reduction.
+ * The `iteratee` should complete with the next state of the reduction.
+ * If the iteratee completes with an error, the reduction is stopped and the
+ * main `callback` is immediately called with the error.
+ * Invoked with (memo, item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result is the reduced value. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ * // file4.txt does not exist
+ *
+ * const fileList = ['file1.txt','file2.txt','file3.txt'];
+ * const withMissingFileList = ['file1.txt','file2.txt','file3.txt', 'file4.txt'];
+ *
+ * // asynchronous function that computes the file size in bytes
+ * // file size is added to the memoized value, then returned
+ * function getFileSizeInBytes(memo, file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, memo + stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.reduce(fileList, 0, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // 6000
+ *         // which is the sum of the file sizes of the three files
+ *     }
+ * });
+ *
+ * // Error Handling
+ * async.reduce(withMissingFileList, 0, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     } else {
+ *         console.log(result);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.reduce(fileList, 0, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ *     // 6000
+ *     // which is the sum of the file sizes of the three files
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.reduce(withMissingFileList, 0, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.reduce(fileList, 0, getFileSizeInBytes);
+ *         console.log(result);
+ *         // 6000
+ *         // which is the sum of the file sizes of the three files
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes);
+ *         console.log(result);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function reduce(coll, memo, iteratee, callback) {
+    callback = (0, _once2.default)(callback);
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+    return (0, _eachOfSeries2.default)(coll, (x, i, iterCb) => {
+        _iteratee(memo, x, (err, v) => {
+            memo = v;
+            iterCb(err);
+        });
+    }, err => callback(err, memo));
+}
+exports.default = (0, _awaitify2.default)(reduce, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/DoublyLinkedList.js b/node_modules/async/internal/DoublyLinkedList.js
new file mode 100644
index 0000000000000000000000000000000000000000..cd11c3b3a86f2091988a83ba762bf60063e9f30e
--- /dev/null
+++ b/node_modules/async/internal/DoublyLinkedList.js
@@ -0,0 +1,92 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+// Simple doubly linked list (https://en.wikipedia.org/wiki/Doubly_linked_list) implementation
+// used for queues. This implementation assumes that the node provided by the user can be modified
+// to adjust the next and last properties. We implement only the minimal functionality
+// for queue support.
+class DLL {
+    constructor() {
+        this.head = this.tail = null;
+        this.length = 0;
+    }
+
+    removeLink(node) {
+        if (node.prev) node.prev.next = node.next;else this.head = node.next;
+        if (node.next) node.next.prev = node.prev;else this.tail = node.prev;
+
+        node.prev = node.next = null;
+        this.length -= 1;
+        return node;
+    }
+
+    empty() {
+        while (this.head) this.shift();
+        return this;
+    }
+
+    insertAfter(node, newNode) {
+        newNode.prev = node;
+        newNode.next = node.next;
+        if (node.next) node.next.prev = newNode;else this.tail = newNode;
+        node.next = newNode;
+        this.length += 1;
+    }
+
+    insertBefore(node, newNode) {
+        newNode.prev = node.prev;
+        newNode.next = node;
+        if (node.prev) node.prev.next = newNode;else this.head = newNode;
+        node.prev = newNode;
+        this.length += 1;
+    }
+
+    unshift(node) {
+        if (this.head) this.insertBefore(this.head, node);else setInitial(this, node);
+    }
+
+    push(node) {
+        if (this.tail) this.insertAfter(this.tail, node);else setInitial(this, node);
+    }
+
+    shift() {
+        return this.head && this.removeLink(this.head);
+    }
+
+    pop() {
+        return this.tail && this.removeLink(this.tail);
+    }
+
+    toArray() {
+        return [...this];
+    }
+
+    *[Symbol.iterator]() {
+        var cur = this.head;
+        while (cur) {
+            yield cur.data;
+            cur = cur.next;
+        }
+    }
+
+    remove(testFn) {
+        var curr = this.head;
+        while (curr) {
+            var { next } = curr;
+            if (testFn(curr)) {
+                this.removeLink(curr);
+            }
+            curr = next;
+        }
+        return this;
+    }
+}
+
+exports.default = DLL;
+function setInitial(dll, node) {
+    dll.length = 1;
+    dll.head = dll.tail = node;
+}
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/internal/Heap.js b/node_modules/async/internal/Heap.js
new file mode 100644
index 0000000000000000000000000000000000000000..80762fe0ed775d54d264645f66e12ff2ef3bd7fd
--- /dev/null
+++ b/node_modules/async/internal/Heap.js
@@ -0,0 +1,120 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+// Binary min-heap implementation used for priority queue.
+// Implementation is stable, i.e. push time is considered for equal priorities
+class Heap {
+    constructor() {
+        this.heap = [];
+        this.pushCount = Number.MIN_SAFE_INTEGER;
+    }
+
+    get length() {
+        return this.heap.length;
+    }
+
+    empty() {
+        this.heap = [];
+        return this;
+    }
+
+    percUp(index) {
+        let p;
+
+        while (index > 0 && smaller(this.heap[index], this.heap[p = parent(index)])) {
+            let t = this.heap[index];
+            this.heap[index] = this.heap[p];
+            this.heap[p] = t;
+
+            index = p;
+        }
+    }
+
+    percDown(index) {
+        let l;
+
+        while ((l = leftChi(index)) < this.heap.length) {
+            if (l + 1 < this.heap.length && smaller(this.heap[l + 1], this.heap[l])) {
+                l = l + 1;
+            }
+
+            if (smaller(this.heap[index], this.heap[l])) {
+                break;
+            }
+
+            let t = this.heap[index];
+            this.heap[index] = this.heap[l];
+            this.heap[l] = t;
+
+            index = l;
+        }
+    }
+
+    push(node) {
+        node.pushCount = ++this.pushCount;
+        this.heap.push(node);
+        this.percUp(this.heap.length - 1);
+    }
+
+    unshift(node) {
+        return this.heap.push(node);
+    }
+
+    shift() {
+        let [top] = this.heap;
+
+        this.heap[0] = this.heap[this.heap.length - 1];
+        this.heap.pop();
+        this.percDown(0);
+
+        return top;
+    }
+
+    toArray() {
+        return [...this];
+    }
+
+    *[Symbol.iterator]() {
+        for (let i = 0; i < this.heap.length; i++) {
+            yield this.heap[i].data;
+        }
+    }
+
+    remove(testFn) {
+        let j = 0;
+        for (let i = 0; i < this.heap.length; i++) {
+            if (!testFn(this.heap[i])) {
+                this.heap[j] = this.heap[i];
+                j++;
+            }
+        }
+
+        this.heap.splice(j);
+
+        for (let i = parent(this.heap.length - 1); i >= 0; i--) {
+            this.percDown(i);
+        }
+
+        return this;
+    }
+}
+
+exports.default = Heap;
+function leftChi(i) {
+    return (i << 1) + 1;
+}
+
+function parent(i) {
+    return (i + 1 >> 1) - 1;
+}
+
+function smaller(x, y) {
+    if (x.priority !== y.priority) {
+        return x.priority < y.priority;
+    } else {
+        return x.pushCount < y.pushCount;
+    }
+}
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/internal/applyEach.js b/node_modules/async/internal/applyEach.js
new file mode 100644
index 0000000000000000000000000000000000000000..a3f4ef1d8c247ccfc40f02d754253f6818e81847
--- /dev/null
+++ b/node_modules/async/internal/applyEach.js
@@ -0,0 +1,29 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+exports.default = function (eachfn) {
+    return function applyEach(fns, ...callArgs) {
+        const go = (0, _awaitify2.default)(function (callback) {
+            var that = this;
+            return eachfn(fns, (fn, cb) => {
+                (0, _wrapAsync2.default)(fn).apply(that, callArgs.concat(cb));
+            }, callback);
+        });
+        return go;
+    };
+};
+
+var _wrapAsync = require('./wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/asyncEachOfLimit.js b/node_modules/async/internal/asyncEachOfLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..bba74c7c9b4efb196e53bb9ce459763dc5c36aca
--- /dev/null
+++ b/node_modules/async/internal/asyncEachOfLimit.js
@@ -0,0 +1,75 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = asyncEachOfLimit;
+
+var _breakLoop = require('./breakLoop.js');
+
+var _breakLoop2 = _interopRequireDefault(_breakLoop);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+// for async generators
+function asyncEachOfLimit(generator, limit, iteratee, callback) {
+    let done = false;
+    let canceled = false;
+    let awaiting = false;
+    let running = 0;
+    let idx = 0;
+
+    function replenish() {
+        //console.log('replenish')
+        if (running >= limit || awaiting || done) return;
+        //console.log('replenish awaiting')
+        awaiting = true;
+        generator.next().then(({ value, done: iterDone }) => {
+            //console.log('got value', value)
+            if (canceled || done) return;
+            awaiting = false;
+            if (iterDone) {
+                done = true;
+                if (running <= 0) {
+                    //console.log('done nextCb')
+                    callback(null);
+                }
+                return;
+            }
+            running++;
+            iteratee(value, idx, iterateeCallback);
+            idx++;
+            replenish();
+        }).catch(handleError);
+    }
+
+    function iterateeCallback(err, result) {
+        //console.log('iterateeCallback')
+        running -= 1;
+        if (canceled) return;
+        if (err) return handleError(err);
+
+        if (err === false) {
+            done = true;
+            canceled = true;
+            return;
+        }
+
+        if (result === _breakLoop2.default || done && running <= 0) {
+            done = true;
+            //console.log('done iterCb')
+            return callback(null);
+        }
+        replenish();
+    }
+
+    function handleError(err) {
+        if (canceled) return;
+        awaiting = false;
+        done = true;
+        callback(err);
+    }
+
+    replenish();
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/awaitify.js b/node_modules/async/internal/awaitify.js
new file mode 100644
index 0000000000000000000000000000000000000000..7b36f1acf5b18e04ff866dd0bcf7daae2741410d
--- /dev/null
+++ b/node_modules/async/internal/awaitify.js
@@ -0,0 +1,27 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = awaitify;
+// conditionally promisify a function.
+// only return a promise if a callback is omitted
+function awaitify(asyncFn, arity = asyncFn.length) {
+    if (!arity) throw new Error('arity is undefined');
+    function awaitable(...args) {
+        if (typeof args[arity - 1] === 'function') {
+            return asyncFn.apply(this, args);
+        }
+
+        return new Promise((resolve, reject) => {
+            args[arity - 1] = (err, ...cbArgs) => {
+                if (err) return reject(err);
+                resolve(cbArgs.length > 1 ? cbArgs : cbArgs[0]);
+            };
+            asyncFn.apply(this, args);
+        });
+    }
+
+    return awaitable;
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/breakLoop.js b/node_modules/async/internal/breakLoop.js
new file mode 100644
index 0000000000000000000000000000000000000000..8245e553eb6d4e36cec2fdc9e80a77888cc6815f
--- /dev/null
+++ b/node_modules/async/internal/breakLoop.js
@@ -0,0 +1,10 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+// A temporary value used to identify if the loop should be broken.
+// See #1064, #1293
+const breakLoop = {};
+exports.default = breakLoop;
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/internal/consoleFunc.js b/node_modules/async/internal/consoleFunc.js
new file mode 100644
index 0000000000000000000000000000000000000000..70347a5d33a869231fc9761440ea1b7f2455ab0e
--- /dev/null
+++ b/node_modules/async/internal/consoleFunc.js
@@ -0,0 +1,31 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = consoleFunc;
+
+var _wrapAsync = require('./wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function consoleFunc(name) {
+    return (fn, ...args) => (0, _wrapAsync2.default)(fn)(...args, (err, ...resultArgs) => {
+        /* istanbul ignore else */
+        if (typeof console === 'object') {
+            /* istanbul ignore else */
+            if (err) {
+                /* istanbul ignore else */
+                if (console.error) {
+                    console.error(err);
+                }
+            } else if (console[name]) {
+                /* istanbul ignore else */
+                resultArgs.forEach(x => console[name](x));
+            }
+        }
+    });
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/createTester.js b/node_modules/async/internal/createTester.js
new file mode 100644
index 0000000000000000000000000000000000000000..7b2d73464538a95fc989ad41391e75e95c368486
--- /dev/null
+++ b/node_modules/async/internal/createTester.js
@@ -0,0 +1,40 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = _createTester;
+
+var _breakLoop = require('./breakLoop.js');
+
+var _breakLoop2 = _interopRequireDefault(_breakLoop);
+
+var _wrapAsync = require('./wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _createTester(check, getResult) {
+    return (eachfn, arr, _iteratee, cb) => {
+        var testPassed = false;
+        var testResult;
+        const iteratee = (0, _wrapAsync2.default)(_iteratee);
+        eachfn(arr, (value, _, callback) => {
+            iteratee(value, (err, result) => {
+                if (err || err === false) return callback(err);
+
+                if (check(result) && !testResult) {
+                    testPassed = true;
+                    testResult = getResult(true, value);
+                    return callback(null, _breakLoop2.default);
+                }
+                callback();
+            });
+        }, err => {
+            if (err) return cb(err);
+            cb(null, testPassed ? testResult : getResult(false));
+        });
+    };
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/eachOfLimit.js b/node_modules/async/internal/eachOfLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..fc26b20fc89e11fd9a1e8a197c61cdc514dc8015
--- /dev/null
+++ b/node_modules/async/internal/eachOfLimit.js
@@ -0,0 +1,90 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _once = require('./once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _iterator = require('./iterator.js');
+
+var _iterator2 = _interopRequireDefault(_iterator);
+
+var _onlyOnce = require('./onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _wrapAsync = require('./wrapAsync.js');
+
+var _asyncEachOfLimit = require('./asyncEachOfLimit.js');
+
+var _asyncEachOfLimit2 = _interopRequireDefault(_asyncEachOfLimit);
+
+var _breakLoop = require('./breakLoop.js');
+
+var _breakLoop2 = _interopRequireDefault(_breakLoop);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = limit => {
+    return (obj, iteratee, callback) => {
+        callback = (0, _once2.default)(callback);
+        if (limit <= 0) {
+            throw new RangeError('concurrency limit cannot be less than 1');
+        }
+        if (!obj) {
+            return callback(null);
+        }
+        if ((0, _wrapAsync.isAsyncGenerator)(obj)) {
+            return (0, _asyncEachOfLimit2.default)(obj, limit, iteratee, callback);
+        }
+        if ((0, _wrapAsync.isAsyncIterable)(obj)) {
+            return (0, _asyncEachOfLimit2.default)(obj[Symbol.asyncIterator](), limit, iteratee, callback);
+        }
+        var nextElem = (0, _iterator2.default)(obj);
+        var done = false;
+        var canceled = false;
+        var running = 0;
+        var looping = false;
+
+        function iterateeCallback(err, value) {
+            if (canceled) return;
+            running -= 1;
+            if (err) {
+                done = true;
+                callback(err);
+            } else if (err === false) {
+                done = true;
+                canceled = true;
+            } else if (value === _breakLoop2.default || done && running <= 0) {
+                done = true;
+                return callback(null);
+            } else if (!looping) {
+                replenish();
+            }
+        }
+
+        function replenish() {
+            looping = true;
+            while (running < limit && !done) {
+                var elem = nextElem();
+                if (elem === null) {
+                    done = true;
+                    if (running <= 0) {
+                        callback(null);
+                    }
+                    return;
+                }
+                running += 1;
+                iteratee(elem.value, elem.key, (0, _onlyOnce2.default)(iterateeCallback));
+            }
+            looping = false;
+        }
+
+        replenish();
+    };
+};
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/filter.js b/node_modules/async/internal/filter.js
new file mode 100644
index 0000000000000000000000000000000000000000..aef2b9d288002eb06c17854a77c0f7c4b17e4a71
--- /dev/null
+++ b/node_modules/async/internal/filter.js
@@ -0,0 +1,55 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = _filter;
+
+var _isArrayLike = require('./isArrayLike.js');
+
+var _isArrayLike2 = _interopRequireDefault(_isArrayLike);
+
+var _wrapAsync = require('./wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function filterArray(eachfn, arr, iteratee, callback) {
+    var truthValues = new Array(arr.length);
+    eachfn(arr, (x, index, iterCb) => {
+        iteratee(x, (err, v) => {
+            truthValues[index] = !!v;
+            iterCb(err);
+        });
+    }, err => {
+        if (err) return callback(err);
+        var results = [];
+        for (var i = 0; i < arr.length; i++) {
+            if (truthValues[i]) results.push(arr[i]);
+        }
+        callback(null, results);
+    });
+}
+
+function filterGeneric(eachfn, coll, iteratee, callback) {
+    var results = [];
+    eachfn(coll, (x, index, iterCb) => {
+        iteratee(x, (err, v) => {
+            if (err) return iterCb(err);
+            if (v) {
+                results.push({ index, value: x });
+            }
+            iterCb(err);
+        });
+    }, err => {
+        if (err) return callback(err);
+        callback(null, results.sort((a, b) => a.index - b.index).map(v => v.value));
+    });
+}
+
+function _filter(eachfn, coll, iteratee, callback) {
+    var filter = (0, _isArrayLike2.default)(coll) ? filterArray : filterGeneric;
+    return filter(eachfn, coll, (0, _wrapAsync2.default)(iteratee), callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/getIterator.js b/node_modules/async/internal/getIterator.js
new file mode 100644
index 0000000000000000000000000000000000000000..830a54527dbd61fa6afdef3af28fa3ec36ac57bc
--- /dev/null
+++ b/node_modules/async/internal/getIterator.js
@@ -0,0 +1,11 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+exports.default = function (coll) {
+    return coll[Symbol.iterator] && coll[Symbol.iterator]();
+};
+
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/internal/initialParams.js b/node_modules/async/internal/initialParams.js
new file mode 100644
index 0000000000000000000000000000000000000000..245378cfd514b2db7d12d3df36306b9f4f569b11
--- /dev/null
+++ b/node_modules/async/internal/initialParams.js
@@ -0,0 +1,14 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+exports.default = function (fn) {
+    return function (...args /*, callback*/) {
+        var callback = args.pop();
+        return fn.call(this, args, callback);
+    };
+};
+
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/internal/isArrayLike.js b/node_modules/async/internal/isArrayLike.js
new file mode 100644
index 0000000000000000000000000000000000000000..ce07670492d747f12aa37b9a6311e4eef4df9246
--- /dev/null
+++ b/node_modules/async/internal/isArrayLike.js
@@ -0,0 +1,10 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = isArrayLike;
+function isArrayLike(value) {
+    return value && typeof value.length === 'number' && value.length >= 0 && value.length % 1 === 0;
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/iterator.js b/node_modules/async/internal/iterator.js
new file mode 100644
index 0000000000000000000000000000000000000000..90b0223b0737a8413b633b182c4fd1395d3e385f
--- /dev/null
+++ b/node_modules/async/internal/iterator.js
@@ -0,0 +1,57 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = createIterator;
+
+var _isArrayLike = require('./isArrayLike.js');
+
+var _isArrayLike2 = _interopRequireDefault(_isArrayLike);
+
+var _getIterator = require('./getIterator.js');
+
+var _getIterator2 = _interopRequireDefault(_getIterator);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function createArrayIterator(coll) {
+    var i = -1;
+    var len = coll.length;
+    return function next() {
+        return ++i < len ? { value: coll[i], key: i } : null;
+    };
+}
+
+function createES2015Iterator(iterator) {
+    var i = -1;
+    return function next() {
+        var item = iterator.next();
+        if (item.done) return null;
+        i++;
+        return { value: item.value, key: i };
+    };
+}
+
+function createObjectIterator(obj) {
+    var okeys = obj ? Object.keys(obj) : [];
+    var i = -1;
+    var len = okeys.length;
+    return function next() {
+        var key = okeys[++i];
+        if (key === '__proto__') {
+            return next();
+        }
+        return i < len ? { value: obj[key], key } : null;
+    };
+}
+
+function createIterator(coll) {
+    if ((0, _isArrayLike2.default)(coll)) {
+        return createArrayIterator(coll);
+    }
+
+    var iterator = (0, _getIterator2.default)(coll);
+    return iterator ? createES2015Iterator(iterator) : createObjectIterator(coll);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/map.js b/node_modules/async/internal/map.js
new file mode 100644
index 0000000000000000000000000000000000000000..af3fd09880e81c3a027ecbf677d8f560b6a61ca7
--- /dev/null
+++ b/node_modules/async/internal/map.js
@@ -0,0 +1,30 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = _asyncMap;
+
+var _wrapAsync = require('./wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _asyncMap(eachfn, arr, iteratee, callback) {
+    arr = arr || [];
+    var results = [];
+    var counter = 0;
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+
+    return eachfn(arr, (value, _, iterCb) => {
+        var index = counter++;
+        _iteratee(value, (err, v) => {
+            results[index] = v;
+            iterCb(err);
+        });
+    }, err => {
+        callback(err, results);
+    });
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/once.js b/node_modules/async/internal/once.js
new file mode 100644
index 0000000000000000000000000000000000000000..49f37270c4462e5e4f590bc1ee41f333495f06bd
--- /dev/null
+++ b/node_modules/async/internal/once.js
@@ -0,0 +1,17 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = once;
+function once(fn) {
+    function wrapper(...args) {
+        if (fn === null) return;
+        var callFn = fn;
+        fn = null;
+        callFn.apply(this, args);
+    }
+    Object.assign(wrapper, fn);
+    return wrapper;
+}
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/internal/onlyOnce.js b/node_modules/async/internal/onlyOnce.js
new file mode 100644
index 0000000000000000000000000000000000000000..6ad721bd30913ff03480df553f7e26c76591d453
--- /dev/null
+++ b/node_modules/async/internal/onlyOnce.js
@@ -0,0 +1,15 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = onlyOnce;
+function onlyOnce(fn) {
+    return function (...args) {
+        if (fn === null) throw new Error("Callback was already called.");
+        var callFn = fn;
+        fn = null;
+        callFn.apply(this, args);
+    };
+}
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/internal/parallel.js b/node_modules/async/internal/parallel.js
new file mode 100644
index 0000000000000000000000000000000000000000..75741bba0d1d09588cff05fd3577c4647557c468
--- /dev/null
+++ b/node_modules/async/internal/parallel.js
@@ -0,0 +1,34 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _isArrayLike = require('./isArrayLike.js');
+
+var _isArrayLike2 = _interopRequireDefault(_isArrayLike);
+
+var _wrapAsync = require('./wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+exports.default = (0, _awaitify2.default)((eachfn, tasks, callback) => {
+    var results = (0, _isArrayLike2.default)(tasks) ? [] : {};
+
+    eachfn(tasks, (task, key, taskCb) => {
+        (0, _wrapAsync2.default)(task)((err, ...result) => {
+            if (result.length < 2) {
+                [result] = result;
+            }
+            results[key] = result;
+            taskCb(err);
+        });
+    }, err => callback(err, results));
+}, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/promiseCallback.js b/node_modules/async/internal/promiseCallback.js
new file mode 100644
index 0000000000000000000000000000000000000000..17a83016c12b4293bb27ebd20a19540c9567e5e1
--- /dev/null
+++ b/node_modules/async/internal/promiseCallback.js
@@ -0,0 +1,23 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+const PROMISE_SYMBOL = Symbol('promiseCallback');
+
+function promiseCallback() {
+    let resolve, reject;
+    function callback(err, ...args) {
+        if (err) return reject(err);
+        resolve(args.length > 1 ? args : args[0]);
+    }
+
+    callback[PROMISE_SYMBOL] = new Promise((res, rej) => {
+        resolve = res, reject = rej;
+    });
+
+    return callback;
+}
+
+exports.promiseCallback = promiseCallback;
+exports.PROMISE_SYMBOL = PROMISE_SYMBOL;
\ No newline at end of file
diff --git a/node_modules/async/internal/queue.js b/node_modules/async/internal/queue.js
new file mode 100644
index 0000000000000000000000000000000000000000..cbc590d0ded6af5e104ef9b72aaf1bcf1a93f96e
--- /dev/null
+++ b/node_modules/async/internal/queue.js
@@ -0,0 +1,294 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = queue;
+
+var _onlyOnce = require('./onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _setImmediate = require('./setImmediate.js');
+
+var _setImmediate2 = _interopRequireDefault(_setImmediate);
+
+var _DoublyLinkedList = require('./DoublyLinkedList.js');
+
+var _DoublyLinkedList2 = _interopRequireDefault(_DoublyLinkedList);
+
+var _wrapAsync = require('./wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function queue(worker, concurrency, payload) {
+    if (concurrency == null) {
+        concurrency = 1;
+    } else if (concurrency === 0) {
+        throw new RangeError('Concurrency must not be zero');
+    }
+
+    var _worker = (0, _wrapAsync2.default)(worker);
+    var numRunning = 0;
+    var workersList = [];
+    const events = {
+        error: [],
+        drain: [],
+        saturated: [],
+        unsaturated: [],
+        empty: []
+    };
+
+    function on(event, handler) {
+        events[event].push(handler);
+    }
+
+    function once(event, handler) {
+        const handleAndRemove = (...args) => {
+            off(event, handleAndRemove);
+            handler(...args);
+        };
+        events[event].push(handleAndRemove);
+    }
+
+    function off(event, handler) {
+        if (!event) return Object.keys(events).forEach(ev => events[ev] = []);
+        if (!handler) return events[event] = [];
+        events[event] = events[event].filter(ev => ev !== handler);
+    }
+
+    function trigger(event, ...args) {
+        events[event].forEach(handler => handler(...args));
+    }
+
+    var processingScheduled = false;
+    function _insert(data, insertAtFront, rejectOnError, callback) {
+        if (callback != null && typeof callback !== 'function') {
+            throw new Error('task callback must be a function');
+        }
+        q.started = true;
+
+        var res, rej;
+        function promiseCallback(err, ...args) {
+            // we don't care about the error, let the global error handler
+            // deal with it
+            if (err) return rejectOnError ? rej(err) : res();
+            if (args.length <= 1) return res(args[0]);
+            res(args);
+        }
+
+        var item = q._createTaskItem(data, rejectOnError ? promiseCallback : callback || promiseCallback);
+
+        if (insertAtFront) {
+            q._tasks.unshift(item);
+        } else {
+            q._tasks.push(item);
+        }
+
+        if (!processingScheduled) {
+            processingScheduled = true;
+            (0, _setImmediate2.default)(() => {
+                processingScheduled = false;
+                q.process();
+            });
+        }
+
+        if (rejectOnError || !callback) {
+            return new Promise((resolve, reject) => {
+                res = resolve;
+                rej = reject;
+            });
+        }
+    }
+
+    function _createCB(tasks) {
+        return function (err, ...args) {
+            numRunning -= 1;
+
+            for (var i = 0, l = tasks.length; i < l; i++) {
+                var task = tasks[i];
+
+                var index = workersList.indexOf(task);
+                if (index === 0) {
+                    workersList.shift();
+                } else if (index > 0) {
+                    workersList.splice(index, 1);
+                }
+
+                task.callback(err, ...args);
+
+                if (err != null) {
+                    trigger('error', err, task.data);
+                }
+            }
+
+            if (numRunning <= q.concurrency - q.buffer) {
+                trigger('unsaturated');
+            }
+
+            if (q.idle()) {
+                trigger('drain');
+            }
+            q.process();
+        };
+    }
+
+    function _maybeDrain(data) {
+        if (data.length === 0 && q.idle()) {
+            // call drain immediately if there are no tasks
+            (0, _setImmediate2.default)(() => trigger('drain'));
+            return true;
+        }
+        return false;
+    }
+
+    const eventMethod = name => handler => {
+        if (!handler) {
+            return new Promise((resolve, reject) => {
+                once(name, (err, data) => {
+                    if (err) return reject(err);
+                    resolve(data);
+                });
+            });
+        }
+        off(name);
+        on(name, handler);
+    };
+
+    var isProcessing = false;
+    var q = {
+        _tasks: new _DoublyLinkedList2.default(),
+        _createTaskItem(data, callback) {
+            return {
+                data,
+                callback
+            };
+        },
+        *[Symbol.iterator]() {
+            yield* q._tasks[Symbol.iterator]();
+        },
+        concurrency,
+        payload,
+        buffer: concurrency / 4,
+        started: false,
+        paused: false,
+        push(data, callback) {
+            if (Array.isArray(data)) {
+                if (_maybeDrain(data)) return;
+                return data.map(datum => _insert(datum, false, false, callback));
+            }
+            return _insert(data, false, false, callback);
+        },
+        pushAsync(data, callback) {
+            if (Array.isArray(data)) {
+                if (_maybeDrain(data)) return;
+                return data.map(datum => _insert(datum, false, true, callback));
+            }
+            return _insert(data, false, true, callback);
+        },
+        kill() {
+            off();
+            q._tasks.empty();
+        },
+        unshift(data, callback) {
+            if (Array.isArray(data)) {
+                if (_maybeDrain(data)) return;
+                return data.map(datum => _insert(datum, true, false, callback));
+            }
+            return _insert(data, true, false, callback);
+        },
+        unshiftAsync(data, callback) {
+            if (Array.isArray(data)) {
+                if (_maybeDrain(data)) return;
+                return data.map(datum => _insert(datum, true, true, callback));
+            }
+            return _insert(data, true, true, callback);
+        },
+        remove(testFn) {
+            q._tasks.remove(testFn);
+        },
+        process() {
+            // Avoid trying to start too many processing operations. This can occur
+            // when callbacks resolve synchronously (#1267).
+            if (isProcessing) {
+                return;
+            }
+            isProcessing = true;
+            while (!q.paused && numRunning < q.concurrency && q._tasks.length) {
+                var tasks = [],
+                    data = [];
+                var l = q._tasks.length;
+                if (q.payload) l = Math.min(l, q.payload);
+                for (var i = 0; i < l; i++) {
+                    var node = q._tasks.shift();
+                    tasks.push(node);
+                    workersList.push(node);
+                    data.push(node.data);
+                }
+
+                numRunning += 1;
+
+                if (q._tasks.length === 0) {
+                    trigger('empty');
+                }
+
+                if (numRunning === q.concurrency) {
+                    trigger('saturated');
+                }
+
+                var cb = (0, _onlyOnce2.default)(_createCB(tasks));
+                _worker(data, cb);
+            }
+            isProcessing = false;
+        },
+        length() {
+            return q._tasks.length;
+        },
+        running() {
+            return numRunning;
+        },
+        workersList() {
+            return workersList;
+        },
+        idle() {
+            return q._tasks.length + numRunning === 0;
+        },
+        pause() {
+            q.paused = true;
+        },
+        resume() {
+            if (q.paused === false) {
+                return;
+            }
+            q.paused = false;
+            (0, _setImmediate2.default)(q.process);
+        }
+    };
+    // define these as fixed properties, so people get useful errors when updating
+    Object.defineProperties(q, {
+        saturated: {
+            writable: false,
+            value: eventMethod('saturated')
+        },
+        unsaturated: {
+            writable: false,
+            value: eventMethod('unsaturated')
+        },
+        empty: {
+            writable: false,
+            value: eventMethod('empty')
+        },
+        drain: {
+            writable: false,
+            value: eventMethod('drain')
+        },
+        error: {
+            writable: false,
+            value: eventMethod('error')
+        }
+    });
+    return q;
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/range.js b/node_modules/async/internal/range.js
new file mode 100644
index 0000000000000000000000000000000000000000..6680e6420a9a7d304710f428a20d09c49c8fd071
--- /dev/null
+++ b/node_modules/async/internal/range.js
@@ -0,0 +1,14 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = range;
+function range(size) {
+    var result = Array(size);
+    while (size--) {
+        result[size] = size;
+    }
+    return result;
+}
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/internal/reject.js b/node_modules/async/internal/reject.js
new file mode 100644
index 0000000000000000000000000000000000000000..7388ef495cc24124899fd321e87236ab6cf3f353
--- /dev/null
+++ b/node_modules/async/internal/reject.js
@@ -0,0 +1,26 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = reject;
+
+var _filter = require('./filter.js');
+
+var _filter2 = _interopRequireDefault(_filter);
+
+var _wrapAsync = require('./wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function reject(eachfn, arr, _iteratee, callback) {
+    const iteratee = (0, _wrapAsync2.default)(_iteratee);
+    return (0, _filter2.default)(eachfn, arr, (value, cb) => {
+        iteratee(value, (err, v) => {
+            cb(err, !v);
+        });
+    }, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/internal/setImmediate.js b/node_modules/async/internal/setImmediate.js
new file mode 100644
index 0000000000000000000000000000000000000000..513efd13c28363194a5aa7e1a8fd9d12a961bcbe
--- /dev/null
+++ b/node_modules/async/internal/setImmediate.js
@@ -0,0 +1,34 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.fallback = fallback;
+exports.wrap = wrap;
+/* istanbul ignore file */
+
+var hasQueueMicrotask = exports.hasQueueMicrotask = typeof queueMicrotask === 'function' && queueMicrotask;
+var hasSetImmediate = exports.hasSetImmediate = typeof setImmediate === 'function' && setImmediate;
+var hasNextTick = exports.hasNextTick = typeof process === 'object' && typeof process.nextTick === 'function';
+
+function fallback(fn) {
+    setTimeout(fn, 0);
+}
+
+function wrap(defer) {
+    return (fn, ...args) => defer(() => fn(...args));
+}
+
+var _defer;
+
+if (hasQueueMicrotask) {
+    _defer = queueMicrotask;
+} else if (hasSetImmediate) {
+    _defer = setImmediate;
+} else if (hasNextTick) {
+    _defer = process.nextTick;
+} else {
+    _defer = fallback;
+}
+
+exports.default = wrap(_defer);
\ No newline at end of file
diff --git a/node_modules/async/internal/withoutIndex.js b/node_modules/async/internal/withoutIndex.js
new file mode 100644
index 0000000000000000000000000000000000000000..ec45fa35435f56647938776521cbdaaa27d8e330
--- /dev/null
+++ b/node_modules/async/internal/withoutIndex.js
@@ -0,0 +1,10 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = _withoutIndex;
+function _withoutIndex(iteratee) {
+    return (value, index, callback) => iteratee(value, callback);
+}
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/internal/wrapAsync.js b/node_modules/async/internal/wrapAsync.js
new file mode 100644
index 0000000000000000000000000000000000000000..ad4d619868ab1be3a44f753cd98e87ecb483e9c2
--- /dev/null
+++ b/node_modules/async/internal/wrapAsync.js
@@ -0,0 +1,34 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.isAsyncIterable = exports.isAsyncGenerator = exports.isAsync = undefined;
+
+var _asyncify = require('../asyncify.js');
+
+var _asyncify2 = _interopRequireDefault(_asyncify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function isAsync(fn) {
+    return fn[Symbol.toStringTag] === 'AsyncFunction';
+}
+
+function isAsyncGenerator(fn) {
+    return fn[Symbol.toStringTag] === 'AsyncGenerator';
+}
+
+function isAsyncIterable(obj) {
+    return typeof obj[Symbol.asyncIterator] === 'function';
+}
+
+function wrapAsync(asyncFn) {
+    if (typeof asyncFn !== 'function') throw new Error('expected a function');
+    return isAsync(asyncFn) ? (0, _asyncify2.default)(asyncFn) : asyncFn;
+}
+
+exports.default = wrapAsync;
+exports.isAsync = isAsync;
+exports.isAsyncGenerator = isAsyncGenerator;
+exports.isAsyncIterable = isAsyncIterable;
\ No newline at end of file
diff --git a/node_modules/async/lib/async.js b/node_modules/async/lib/async.js
deleted file mode 100644
index 394c41cada09550b30185e664efdf08661705d3b..0000000000000000000000000000000000000000
--- a/node_modules/async/lib/async.js
+++ /dev/null
@@ -1,1123 +0,0 @@
-/*!
- * async
- * https://github.com/caolan/async
- *
- * Copyright 2010-2014 Caolan McMahon
- * Released under the MIT license
- */
-/*jshint onevar: false, indent:4 */
-/*global setImmediate: false, setTimeout: false, console: false */
-(function () {
-
-    var async = {};
-
-    // global on the server, window in the browser
-    var root, previous_async;
-
-    root = this;
-    if (root != null) {
-      previous_async = root.async;
-    }
-
-    async.noConflict = function () {
-        root.async = previous_async;
-        return async;
-    };
-
-    function only_once(fn) {
-        var called = false;
-        return function() {
-            if (called) throw new Error("Callback was already called.");
-            called = true;
-            fn.apply(root, arguments);
-        }
-    }
-
-    //// cross-browser compatiblity functions ////
-
-    var _toString = Object.prototype.toString;
-
-    var _isArray = Array.isArray || function (obj) {
-        return _toString.call(obj) === '[object Array]';
-    };
-
-    var _each = function (arr, iterator) {
-        for (var i = 0; i < arr.length; i += 1) {
-            iterator(arr[i], i, arr);
-        }
-    };
-
-    var _map = function (arr, iterator) {
-        if (arr.map) {
-            return arr.map(iterator);
-        }
-        var results = [];
-        _each(arr, function (x, i, a) {
-            results.push(iterator(x, i, a));
-        });
-        return results;
-    };
-
-    var _reduce = function (arr, iterator, memo) {
-        if (arr.reduce) {
-            return arr.reduce(iterator, memo);
-        }
-        _each(arr, function (x, i, a) {
-            memo = iterator(memo, x, i, a);
-        });
-        return memo;
-    };
-
-    var _keys = function (obj) {
-        if (Object.keys) {
-            return Object.keys(obj);
-        }
-        var keys = [];
-        for (var k in obj) {
-            if (obj.hasOwnProperty(k)) {
-                keys.push(k);
-            }
-        }
-        return keys;
-    };
-
-    //// exported async module functions ////
-
-    //// nextTick implementation with browser-compatible fallback ////
-    if (typeof process === 'undefined' || !(process.nextTick)) {
-        if (typeof setImmediate === 'function') {
-            async.nextTick = function (fn) {
-                // not a direct alias for IE10 compatibility
-                setImmediate(fn);
-            };
-            async.setImmediate = async.nextTick;
-        }
-        else {
-            async.nextTick = function (fn) {
-                setTimeout(fn, 0);
-            };
-            async.setImmediate = async.nextTick;
-        }
-    }
-    else {
-        async.nextTick = process.nextTick;
-        if (typeof setImmediate !== 'undefined') {
-            async.setImmediate = function (fn) {
-              // not a direct alias for IE10 compatibility
-              setImmediate(fn);
-            };
-        }
-        else {
-            async.setImmediate = async.nextTick;
-        }
-    }
-
-    async.each = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
-        }
-        var completed = 0;
-        _each(arr, function (x) {
-            iterator(x, only_once(done) );
-        });
-        function done(err) {
-          if (err) {
-              callback(err);
-              callback = function () {};
-          }
-          else {
-              completed += 1;
-              if (completed >= arr.length) {
-                  callback();
-              }
-          }
-        }
-    };
-    async.forEach = async.each;
-
-    async.eachSeries = function (arr, iterator, callback) {
-        callback = callback || function () {};
-        if (!arr.length) {
-            return callback();
-        }
-        var completed = 0;
-        var iterate = function () {
-            iterator(arr[completed], function (err) {
-                if (err) {
-                    callback(err);
-                    callback = function () {};
-                }
-                else {
-                    completed += 1;
-                    if (completed >= arr.length) {
-                        callback();
-                    }
-                    else {
-                        iterate();
-                    }
-                }
-            });
-        };
-        iterate();
-    };
-    async.forEachSeries = async.eachSeries;
-
-    async.eachLimit = function (arr, limit, iterator, callback) {
-        var fn = _eachLimit(limit);
-        fn.apply(null, [arr, iterator, callback]);
-    };
-    async.forEachLimit = async.eachLimit;
-
-    var _eachLimit = function (limit) {
-
-        return function (arr, iterator, callback) {
-            callback = callback || function () {};
-            if (!arr.length || limit <= 0) {
-                return callback();
-            }
-            var completed = 0;
-            var started = 0;
-            var running = 0;
-
-            (function replenish () {
-                if (completed >= arr.length) {
-                    return callback();
-                }
-
-                while (running < limit && started < arr.length) {
-                    started += 1;
-                    running += 1;
-                    iterator(arr[started - 1], function (err) {
-                        if (err) {
-                            callback(err);
-                            callback = function () {};
-                        }
-                        else {
-                            completed += 1;
-                            running -= 1;
-                            if (completed >= arr.length) {
-                                callback();
-                            }
-                            else {
-                                replenish();
-                            }
-                        }
-                    });
-                }
-            })();
-        };
-    };
-
-
-    var doParallel = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.each].concat(args));
-        };
-    };
-    var doParallelLimit = function(limit, fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [_eachLimit(limit)].concat(args));
-        };
-    };
-    var doSeries = function (fn) {
-        return function () {
-            var args = Array.prototype.slice.call(arguments);
-            return fn.apply(null, [async.eachSeries].concat(args));
-        };
-    };
-
-
-    var _asyncMap = function (eachfn, arr, iterator, callback) {
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        if (!callback) {
-            eachfn(arr, function (x, callback) {
-                iterator(x.value, function (err) {
-                    callback(err);
-                });
-            });
-        } else {
-            var results = [];
-            eachfn(arr, function (x, callback) {
-                iterator(x.value, function (err, v) {
-                    results[x.index] = v;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
-    async.map = doParallel(_asyncMap);
-    async.mapSeries = doSeries(_asyncMap);
-    async.mapLimit = function (arr, limit, iterator, callback) {
-        return _mapLimit(limit)(arr, iterator, callback);
-    };
-
-    var _mapLimit = function(limit) {
-        return doParallelLimit(limit, _asyncMap);
-    };
-
-    // reduce only has a series version, as doing reduce in parallel won't
-    // work in many situations.
-    async.reduce = function (arr, memo, iterator, callback) {
-        async.eachSeries(arr, function (x, callback) {
-            iterator(memo, x, function (err, v) {
-                memo = v;
-                callback(err);
-            });
-        }, function (err) {
-            callback(err, memo);
-        });
-    };
-    // inject alias
-    async.inject = async.reduce;
-    // foldl alias
-    async.foldl = async.reduce;
-
-    async.reduceRight = function (arr, memo, iterator, callback) {
-        var reversed = _map(arr, function (x) {
-            return x;
-        }).reverse();
-        async.reduce(reversed, memo, iterator, callback);
-    };
-    // foldr alias
-    async.foldr = async.reduceRight;
-
-    var _filter = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
-                if (v) {
-                    results.push(x);
-                }
-                callback();
-            });
-        }, function (err) {
-            callback(_map(results.sort(function (a, b) {
-                return a.index - b.index;
-            }), function (x) {
-                return x.value;
-            }));
-        });
-    };
-    async.filter = doParallel(_filter);
-    async.filterSeries = doSeries(_filter);
-    // select alias
-    async.select = async.filter;
-    async.selectSeries = async.filterSeries;
-
-    var _reject = function (eachfn, arr, iterator, callback) {
-        var results = [];
-        arr = _map(arr, function (x, i) {
-            return {index: i, value: x};
-        });
-        eachfn(arr, function (x, callback) {
-            iterator(x.value, function (v) {
-                if (!v) {
-                    results.push(x);
-                }
-                callback();
-            });
-        }, function (err) {
-            callback(_map(results.sort(function (a, b) {
-                return a.index - b.index;
-            }), function (x) {
-                return x.value;
-            }));
-        });
-    };
-    async.reject = doParallel(_reject);
-    async.rejectSeries = doSeries(_reject);
-
-    var _detect = function (eachfn, arr, iterator, main_callback) {
-        eachfn(arr, function (x, callback) {
-            iterator(x, function (result) {
-                if (result) {
-                    main_callback(x);
-                    main_callback = function () {};
-                }
-                else {
-                    callback();
-                }
-            });
-        }, function (err) {
-            main_callback();
-        });
-    };
-    async.detect = doParallel(_detect);
-    async.detectSeries = doSeries(_detect);
-
-    async.some = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (v) {
-                    main_callback(true);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(false);
-        });
-    };
-    // any alias
-    async.any = async.some;
-
-    async.every = function (arr, iterator, main_callback) {
-        async.each(arr, function (x, callback) {
-            iterator(x, function (v) {
-                if (!v) {
-                    main_callback(false);
-                    main_callback = function () {};
-                }
-                callback();
-            });
-        }, function (err) {
-            main_callback(true);
-        });
-    };
-    // all alias
-    async.all = async.every;
-
-    async.sortBy = function (arr, iterator, callback) {
-        async.map(arr, function (x, callback) {
-            iterator(x, function (err, criteria) {
-                if (err) {
-                    callback(err);
-                }
-                else {
-                    callback(null, {value: x, criteria: criteria});
-                }
-            });
-        }, function (err, results) {
-            if (err) {
-                return callback(err);
-            }
-            else {
-                var fn = function (left, right) {
-                    var a = left.criteria, b = right.criteria;
-                    return a < b ? -1 : a > b ? 1 : 0;
-                };
-                callback(null, _map(results.sort(fn), function (x) {
-                    return x.value;
-                }));
-            }
-        });
-    };
-
-    async.auto = function (tasks, callback) {
-        callback = callback || function () {};
-        var keys = _keys(tasks);
-        var remainingTasks = keys.length
-        if (!remainingTasks) {
-            return callback();
-        }
-
-        var results = {};
-
-        var listeners = [];
-        var addListener = function (fn) {
-            listeners.unshift(fn);
-        };
-        var removeListener = function (fn) {
-            for (var i = 0; i < listeners.length; i += 1) {
-                if (listeners[i] === fn) {
-                    listeners.splice(i, 1);
-                    return;
-                }
-            }
-        };
-        var taskComplete = function () {
-            remainingTasks--
-            _each(listeners.slice(0), function (fn) {
-                fn();
-            });
-        };
-
-        addListener(function () {
-            if (!remainingTasks) {
-                var theCallback = callback;
-                // prevent final callback from calling itself if it errors
-                callback = function () {};
-
-                theCallback(null, results);
-            }
-        });
-
-        _each(keys, function (k) {
-            var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
-            var taskCallback = function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
-                if (args.length <= 1) {
-                    args = args[0];
-                }
-                if (err) {
-                    var safeResults = {};
-                    _each(_keys(results), function(rkey) {
-                        safeResults[rkey] = results[rkey];
-                    });
-                    safeResults[k] = args;
-                    callback(err, safeResults);
-                    // stop subsequent errors hitting callback multiple times
-                    callback = function () {};
-                }
-                else {
-                    results[k] = args;
-                    async.setImmediate(taskComplete);
-                }
-            };
-            var requires = task.slice(0, Math.abs(task.length - 1)) || [];
-            var ready = function () {
-                return _reduce(requires, function (a, x) {
-                    return (a && results.hasOwnProperty(x));
-                }, true) && !results.hasOwnProperty(k);
-            };
-            if (ready()) {
-                task[task.length - 1](taskCallback, results);
-            }
-            else {
-                var listener = function () {
-                    if (ready()) {
-                        removeListener(listener);
-                        task[task.length - 1](taskCallback, results);
-                    }
-                };
-                addListener(listener);
-            }
-        });
-    };
-
-    async.retry = function(times, task, callback) {
-        var DEFAULT_TIMES = 5;
-        var attempts = [];
-        // Use defaults if times not passed
-        if (typeof times === 'function') {
-            callback = task;
-            task = times;
-            times = DEFAULT_TIMES;
-        }
-        // Make sure times is a number
-        times = parseInt(times, 10) || DEFAULT_TIMES;
-        var wrappedTask = function(wrappedCallback, wrappedResults) {
-            var retryAttempt = function(task, finalAttempt) {
-                return function(seriesCallback) {
-                    task(function(err, result){
-                        seriesCallback(!err || finalAttempt, {err: err, result: result});
-                    }, wrappedResults);
-                };
-            };
-            while (times) {
-                attempts.push(retryAttempt(task, !(times-=1)));
-            }
-            async.series(attempts, function(done, data){
-                data = data[data.length - 1];
-                (wrappedCallback || callback)(data.err, data.result);
-            });
-        }
-        // If a callback is passed, run this as a controll flow
-        return callback ? wrappedTask() : wrappedTask
-    };
-
-    async.waterfall = function (tasks, callback) {
-        callback = callback || function () {};
-        if (!_isArray(tasks)) {
-          var err = new Error('First argument to waterfall must be an array of functions');
-          return callback(err);
-        }
-        if (!tasks.length) {
-            return callback();
-        }
-        var wrapIterator = function (iterator) {
-            return function (err) {
-                if (err) {
-                    callback.apply(null, arguments);
-                    callback = function () {};
-                }
-                else {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    var next = iterator.next();
-                    if (next) {
-                        args.push(wrapIterator(next));
-                    }
-                    else {
-                        args.push(callback);
-                    }
-                    async.setImmediate(function () {
-                        iterator.apply(null, args);
-                    });
-                }
-            };
-        };
-        wrapIterator(async.iterator(tasks))();
-    };
-
-    var _parallel = function(eachfn, tasks, callback) {
-        callback = callback || function () {};
-        if (_isArray(tasks)) {
-            eachfn.map(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
-                        }
-                        callback.call(null, err, args);
-                    });
-                }
-            }, callback);
-        }
-        else {
-            var results = {};
-            eachfn.each(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
-
-    async.parallel = function (tasks, callback) {
-        _parallel({ map: async.map, each: async.each }, tasks, callback);
-    };
-
-    async.parallelLimit = function(tasks, limit, callback) {
-        _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
-    };
-
-    async.series = function (tasks, callback) {
-        callback = callback || function () {};
-        if (_isArray(tasks)) {
-            async.mapSeries(tasks, function (fn, callback) {
-                if (fn) {
-                    fn(function (err) {
-                        var args = Array.prototype.slice.call(arguments, 1);
-                        if (args.length <= 1) {
-                            args = args[0];
-                        }
-                        callback.call(null, err, args);
-                    });
-                }
-            }, callback);
-        }
-        else {
-            var results = {};
-            async.eachSeries(_keys(tasks), function (k, callback) {
-                tasks[k](function (err) {
-                    var args = Array.prototype.slice.call(arguments, 1);
-                    if (args.length <= 1) {
-                        args = args[0];
-                    }
-                    results[k] = args;
-                    callback(err);
-                });
-            }, function (err) {
-                callback(err, results);
-            });
-        }
-    };
-
-    async.iterator = function (tasks) {
-        var makeCallback = function (index) {
-            var fn = function () {
-                if (tasks.length) {
-                    tasks[index].apply(null, arguments);
-                }
-                return fn.next();
-            };
-            fn.next = function () {
-                return (index < tasks.length - 1) ? makeCallback(index + 1): null;
-            };
-            return fn;
-        };
-        return makeCallback(0);
-    };
-
-    async.apply = function (fn) {
-        var args = Array.prototype.slice.call(arguments, 1);
-        return function () {
-            return fn.apply(
-                null, args.concat(Array.prototype.slice.call(arguments))
-            );
-        };
-    };
-
-    var _concat = function (eachfn, arr, fn, callback) {
-        var r = [];
-        eachfn(arr, function (x, cb) {
-            fn(x, function (err, y) {
-                r = r.concat(y || []);
-                cb(err);
-            });
-        }, function (err) {
-            callback(err, r);
-        });
-    };
-    async.concat = doParallel(_concat);
-    async.concatSeries = doSeries(_concat);
-
-    async.whilst = function (test, iterator, callback) {
-        if (test()) {
-            iterator(function (err) {
-                if (err) {
-                    return callback(err);
-                }
-                async.whilst(test, iterator, callback);
-            });
-        }
-        else {
-            callback();
-        }
-    };
-
-    async.doWhilst = function (iterator, test, callback) {
-        iterator(function (err) {
-            if (err) {
-                return callback(err);
-            }
-            var args = Array.prototype.slice.call(arguments, 1);
-            if (test.apply(null, args)) {
-                async.doWhilst(iterator, test, callback);
-            }
-            else {
-                callback();
-            }
-        });
-    };
-
-    async.until = function (test, iterator, callback) {
-        if (!test()) {
-            iterator(function (err) {
-                if (err) {
-                    return callback(err);
-                }
-                async.until(test, iterator, callback);
-            });
-        }
-        else {
-            callback();
-        }
-    };
-
-    async.doUntil = function (iterator, test, callback) {
-        iterator(function (err) {
-            if (err) {
-                return callback(err);
-            }
-            var args = Array.prototype.slice.call(arguments, 1);
-            if (!test.apply(null, args)) {
-                async.doUntil(iterator, test, callback);
-            }
-            else {
-                callback();
-            }
-        });
-    };
-
-    async.queue = function (worker, concurrency) {
-        if (concurrency === undefined) {
-            concurrency = 1;
-        }
-        function _insert(q, data, pos, callback) {
-          if (!q.started){
-            q.started = true;
-          }
-          if (!_isArray(data)) {
-              data = [data];
-          }
-          if(data.length == 0) {
-             // call drain immediately if there are no tasks
-             return async.setImmediate(function() {
-                 if (q.drain) {
-                     q.drain();
-                 }
-             });
-          }
-          _each(data, function(task) {
-              var item = {
-                  data: task,
-                  callback: typeof callback === 'function' ? callback : null
-              };
-
-              if (pos) {
-                q.tasks.unshift(item);
-              } else {
-                q.tasks.push(item);
-              }
-
-              if (q.saturated && q.tasks.length === q.concurrency) {
-                  q.saturated();
-              }
-              async.setImmediate(q.process);
-          });
-        }
-
-        var workers = 0;
-        var q = {
-            tasks: [],
-            concurrency: concurrency,
-            saturated: null,
-            empty: null,
-            drain: null,
-            started: false,
-            paused: false,
-            push: function (data, callback) {
-              _insert(q, data, false, callback);
-            },
-            kill: function () {
-              q.drain = null;
-              q.tasks = [];
-            },
-            unshift: function (data, callback) {
-              _insert(q, data, true, callback);
-            },
-            process: function () {
-                if (!q.paused && workers < q.concurrency && q.tasks.length) {
-                    var task = q.tasks.shift();
-                    if (q.empty && q.tasks.length === 0) {
-                        q.empty();
-                    }
-                    workers += 1;
-                    var next = function () {
-                        workers -= 1;
-                        if (task.callback) {
-                            task.callback.apply(task, arguments);
-                        }
-                        if (q.drain && q.tasks.length + workers === 0) {
-                            q.drain();
-                        }
-                        q.process();
-                    };
-                    var cb = only_once(next);
-                    worker(task.data, cb);
-                }
-            },
-            length: function () {
-                return q.tasks.length;
-            },
-            running: function () {
-                return workers;
-            },
-            idle: function() {
-                return q.tasks.length + workers === 0;
-            },
-            pause: function () {
-                if (q.paused === true) { return; }
-                q.paused = true;
-            },
-            resume: function () {
-                if (q.paused === false) { return; }
-                q.paused = false;
-                // Need to call q.process once per concurrent
-                // worker to preserve full concurrency after pause
-                for (var w = 1; w <= q.concurrency; w++) {
-                    async.setImmediate(q.process);
-                }
-            }
-        };
-        return q;
-    };
-
-    async.priorityQueue = function (worker, concurrency) {
-
-        function _compareTasks(a, b){
-          return a.priority - b.priority;
-        };
-
-        function _binarySearch(sequence, item, compare) {
-          var beg = -1,
-              end = sequence.length - 1;
-          while (beg < end) {
-            var mid = beg + ((end - beg + 1) >>> 1);
-            if (compare(item, sequence[mid]) >= 0) {
-              beg = mid;
-            } else {
-              end = mid - 1;
-            }
-          }
-          return beg;
-        }
-
-        function _insert(q, data, priority, callback) {
-          if (!q.started){
-            q.started = true;
-          }
-          if (!_isArray(data)) {
-              data = [data];
-          }
-          if(data.length == 0) {
-             // call drain immediately if there are no tasks
-             return async.setImmediate(function() {
-                 if (q.drain) {
-                     q.drain();
-                 }
-             });
-          }
-          _each(data, function(task) {
-              var item = {
-                  data: task,
-                  priority: priority,
-                  callback: typeof callback === 'function' ? callback : null
-              };
-
-              q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
-
-              if (q.saturated && q.tasks.length === q.concurrency) {
-                  q.saturated();
-              }
-              async.setImmediate(q.process);
-          });
-        }
-
-        // Start with a normal queue
-        var q = async.queue(worker, concurrency);
-
-        // Override push to accept second parameter representing priority
-        q.push = function (data, priority, callback) {
-          _insert(q, data, priority, callback);
-        };
-
-        // Remove unshift function
-        delete q.unshift;
-
-        return q;
-    };
-
-    async.cargo = function (worker, payload) {
-        var working     = false,
-            tasks       = [];
-
-        var cargo = {
-            tasks: tasks,
-            payload: payload,
-            saturated: null,
-            empty: null,
-            drain: null,
-            drained: true,
-            push: function (data, callback) {
-                if (!_isArray(data)) {
-                    data = [data];
-                }
-                _each(data, function(task) {
-                    tasks.push({
-                        data: task,
-                        callback: typeof callback === 'function' ? callback : null
-                    });
-                    cargo.drained = false;
-                    if (cargo.saturated && tasks.length === payload) {
-                        cargo.saturated();
-                    }
-                });
-                async.setImmediate(cargo.process);
-            },
-            process: function process() {
-                if (working) return;
-                if (tasks.length === 0) {
-                    if(cargo.drain && !cargo.drained) cargo.drain();
-                    cargo.drained = true;
-                    return;
-                }
-
-                var ts = typeof payload === 'number'
-                            ? tasks.splice(0, payload)
-                            : tasks.splice(0, tasks.length);
-
-                var ds = _map(ts, function (task) {
-                    return task.data;
-                });
-
-                if(cargo.empty) cargo.empty();
-                working = true;
-                worker(ds, function () {
-                    working = false;
-
-                    var args = arguments;
-                    _each(ts, function (data) {
-                        if (data.callback) {
-                            data.callback.apply(null, args);
-                        }
-                    });
-
-                    process();
-                });
-            },
-            length: function () {
-                return tasks.length;
-            },
-            running: function () {
-                return working;
-            }
-        };
-        return cargo;
-    };
-
-    var _console_fn = function (name) {
-        return function (fn) {
-            var args = Array.prototype.slice.call(arguments, 1);
-            fn.apply(null, args.concat([function (err) {
-                var args = Array.prototype.slice.call(arguments, 1);
-                if (typeof console !== 'undefined') {
-                    if (err) {
-                        if (console.error) {
-                            console.error(err);
-                        }
-                    }
-                    else if (console[name]) {
-                        _each(args, function (x) {
-                            console[name](x);
-                        });
-                    }
-                }
-            }]));
-        };
-    };
-    async.log = _console_fn('log');
-    async.dir = _console_fn('dir');
-    /*async.info = _console_fn('info');
-    async.warn = _console_fn('warn');
-    async.error = _console_fn('error');*/
-
-    async.memoize = function (fn, hasher) {
-        var memo = {};
-        var queues = {};
-        hasher = hasher || function (x) {
-            return x;
-        };
-        var memoized = function () {
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            var key = hasher.apply(null, args);
-            if (key in memo) {
-                async.nextTick(function () {
-                    callback.apply(null, memo[key]);
-                });
-            }
-            else if (key in queues) {
-                queues[key].push(callback);
-            }
-            else {
-                queues[key] = [callback];
-                fn.apply(null, args.concat([function () {
-                    memo[key] = arguments;
-                    var q = queues[key];
-                    delete queues[key];
-                    for (var i = 0, l = q.length; i < l; i++) {
-                      q[i].apply(null, arguments);
-                    }
-                }]));
-            }
-        };
-        memoized.memo = memo;
-        memoized.unmemoized = fn;
-        return memoized;
-    };
-
-    async.unmemoize = function (fn) {
-      return function () {
-        return (fn.unmemoized || fn).apply(null, arguments);
-      };
-    };
-
-    async.times = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
-        }
-        return async.map(counter, iterator, callback);
-    };
-
-    async.timesSeries = function (count, iterator, callback) {
-        var counter = [];
-        for (var i = 0; i < count; i++) {
-            counter.push(i);
-        }
-        return async.mapSeries(counter, iterator, callback);
-    };
-
-    async.seq = function (/* functions... */) {
-        var fns = arguments;
-        return function () {
-            var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            async.reduce(fns, args, function (newargs, fn, cb) {
-                fn.apply(that, newargs.concat([function () {
-                    var err = arguments[0];
-                    var nextargs = Array.prototype.slice.call(arguments, 1);
-                    cb(err, nextargs);
-                }]))
-            },
-            function (err, results) {
-                callback.apply(that, [err].concat(results));
-            });
-        };
-    };
-
-    async.compose = function (/* functions... */) {
-      return async.seq.apply(null, Array.prototype.reverse.call(arguments));
-    };
-
-    var _applyEach = function (eachfn, fns /*args...*/) {
-        var go = function () {
-            var that = this;
-            var args = Array.prototype.slice.call(arguments);
-            var callback = args.pop();
-            return eachfn(fns, function (fn, cb) {
-                fn.apply(that, args.concat([cb]));
-            },
-            callback);
-        };
-        if (arguments.length > 2) {
-            var args = Array.prototype.slice.call(arguments, 2);
-            return go.apply(this, args);
-        }
-        else {
-            return go;
-        }
-    };
-    async.applyEach = doParallel(_applyEach);
-    async.applyEachSeries = doSeries(_applyEach);
-
-    async.forever = function (fn, callback) {
-        function next(err) {
-            if (err) {
-                if (callback) {
-                    return callback(err);
-                }
-                throw err;
-            }
-            fn(next);
-        }
-        next();
-    };
-
-    // Node.js
-    if (typeof module !== 'undefined' && module.exports) {
-        module.exports = async;
-    }
-    // AMD / RequireJS
-    else if (typeof define !== 'undefined' && define.amd) {
-        define([], function () {
-            return async;
-        });
-    }
-    // included directly via <script> tag
-    else {
-        root.async = async;
-    }
-
-}());
diff --git a/node_modules/async/log.js b/node_modules/async/log.js
new file mode 100644
index 0000000000000000000000000000000000000000..8fc1ed511f8271ca754f1eb93ae835bc5abb70a4
--- /dev/null
+++ b/node_modules/async/log.js
@@ -0,0 +1,41 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _consoleFunc = require('./internal/consoleFunc.js');
+
+var _consoleFunc2 = _interopRequireDefault(_consoleFunc);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Logs the result of an `async` function to the `console`. Only works in
+ * Node.js or in browsers that support `console.log` and `console.error` (such
+ * as FF and Chrome). If multiple arguments are returned from the async
+ * function, `console.log` is called on each argument in order.
+ *
+ * @name log
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} function - The function you want to eventually apply
+ * all arguments to.
+ * @param {...*} arguments... - Any number of arguments to apply to the function.
+ * @example
+ *
+ * // in a module
+ * var hello = function(name, callback) {
+ *     setTimeout(function() {
+ *         callback(null, 'hello ' + name);
+ *     }, 1000);
+ * };
+ *
+ * // in the node repl
+ * node> async.log(hello, 'world');
+ * 'hello world'
+ */
+exports.default = (0, _consoleFunc2.default)('log');
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/map.js b/node_modules/async/map.js
new file mode 100644
index 0000000000000000000000000000000000000000..ec4135d1388d5ad92fd08c66713fca2b20e26928
--- /dev/null
+++ b/node_modules/async/map.js
@@ -0,0 +1,142 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _map2 = require('./internal/map.js');
+
+var _map3 = _interopRequireDefault(_map2);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Produces a new collection of values by mapping each value in `coll` through
+ * the `iteratee` function. The `iteratee` is called with an item from `coll`
+ * and a callback for when it has finished processing. Each of these callbacks
+ * takes 2 arguments: an `error`, and the transformed item from `coll`. If
+ * `iteratee` passes an error to its callback, the main `callback` (for the
+ * `map` function) is immediately called with the error.
+ *
+ * Note, that since this function applies the `iteratee` to each item in
+ * parallel, there is no guarantee that the `iteratee` functions will complete
+ * in order. However, the results array will be in the same order as the
+ * original `coll`.
+ *
+ * If `map` is passed an Object, the results will be an Array.  The results
+ * will roughly be in the order of the original Objects' keys (but this can
+ * vary across JavaScript engines).
+ *
+ * @name map
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with the transformed item.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Results is an Array of the
+ * transformed items from the `coll`. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ * // file4.txt does not exist
+ *
+ * const fileList = ['file1.txt','file2.txt','file3.txt'];
+ * const withMissingFileList = ['file1.txt','file2.txt','file4.txt'];
+ *
+ * // asynchronous function that returns the file size in bytes
+ * function getFileSizeInBytes(file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.map(fileList, getFileSizeInBytes, function(err, results) {
+ *     if (err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(results);
+ *         // results is now an array of the file size in bytes for each file, e.g.
+ *         // [ 1000, 2000, 3000]
+ *     }
+ * });
+ *
+ * // Error Handling
+ * async.map(withMissingFileList, getFileSizeInBytes, function(err, results) {
+ *     if (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     } else {
+ *         console.log(results);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.map(fileList, getFileSizeInBytes)
+ * .then( results => {
+ *     console.log(results);
+ *     // results is now an array of the file size in bytes for each file, e.g.
+ *     // [ 1000, 2000, 3000]
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.map(withMissingFileList, getFileSizeInBytes)
+ * .then( results => {
+ *     console.log(results);
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.map(fileList, getFileSizeInBytes);
+ *         console.log(results);
+ *         // results is now an array of the file size in bytes for each file, e.g.
+ *         // [ 1000, 2000, 3000]
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let results = await async.map(withMissingFileList, getFileSizeInBytes);
+ *         console.log(results);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function map(coll, iteratee, callback) {
+  return (0, _map3.default)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(map, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/mapLimit.js b/node_modules/async/mapLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..b5e461c37475fc534f4c24ade5381189915a561b
--- /dev/null
+++ b/node_modules/async/mapLimit.js
@@ -0,0 +1,45 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _map2 = require('./internal/map.js');
+
+var _map3 = _interopRequireDefault(_map2);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`map`]{@link module:Collections.map} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name mapLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.map]{@link module:Collections.map}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with the transformed item.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Results is an array of the
+ * transformed items from the `coll`. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function mapLimit(coll, limit, iteratee, callback) {
+  return (0, _map3.default)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(mapLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/mapSeries.js b/node_modules/async/mapSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..91f36bf4f88cdf2b3978fd544e0023aefd538111
--- /dev/null
+++ b/node_modules/async/mapSeries.js
@@ -0,0 +1,44 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _map2 = require('./internal/map.js');
+
+var _map3 = _interopRequireDefault(_map2);
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`map`]{@link module:Collections.map} but runs only a single async operation at a time.
+ *
+ * @name mapSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.map]{@link module:Collections.map}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with the transformed item.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. Results is an array of the
+ * transformed items from the `coll`. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function mapSeries(coll, iteratee, callback) {
+  return (0, _map3.default)(_eachOfSeries2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(mapSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/mapValues.js b/node_modules/async/mapValues.js
new file mode 100644
index 0000000000000000000000000000000000000000..00da9262b5d2df851f7d4b9ab2370857b52cde08
--- /dev/null
+++ b/node_modules/async/mapValues.js
@@ -0,0 +1,152 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = mapValues;
+
+var _mapValuesLimit = require('./mapValuesLimit.js');
+
+var _mapValuesLimit2 = _interopRequireDefault(_mapValuesLimit);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * A relative of [`map`]{@link module:Collections.map}, designed for use with objects.
+ *
+ * Produces a new Object by mapping each value of `obj` through the `iteratee`
+ * function. The `iteratee` is called each `value` and `key` from `obj` and a
+ * callback for when it has finished processing. Each of these callbacks takes
+ * two arguments: an `error`, and the transformed item from `obj`. If `iteratee`
+ * passes an error to its callback, the main `callback` (for the `mapValues`
+ * function) is immediately called with the error.
+ *
+ * Note, the order of the keys in the result is not guaranteed.  The keys will
+ * be roughly in the order they complete, (but this is very engine-specific)
+ *
+ * @name mapValues
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Object} obj - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each value and key
+ * in `coll`.
+ * The iteratee should complete with the transformed value as its result.
+ * Invoked with (value, key, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. `result` is a new object consisting
+ * of each key from `obj`, with each transformed value on the right-hand side.
+ * Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ * // file4.txt does not exist
+ *
+ * const fileMap = {
+ *     f1: 'file1.txt',
+ *     f2: 'file2.txt',
+ *     f3: 'file3.txt'
+ * };
+ *
+ * const withMissingFileMap = {
+ *     f1: 'file1.txt',
+ *     f2: 'file2.txt',
+ *     f3: 'file4.txt'
+ * };
+ *
+ * // asynchronous function that returns the file size in bytes
+ * function getFileSizeInBytes(file, key, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.mapValues(fileMap, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // result is now a map of file size in bytes for each file, e.g.
+ *         // {
+ *         //     f1: 1000,
+ *         //     f2: 2000,
+ *         //     f3: 3000
+ *         // }
+ *     }
+ * });
+ *
+ * // Error handling
+ * async.mapValues(withMissingFileMap, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     } else {
+ *         console.log(result);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.mapValues(fileMap, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ *     // result is now a map of file size in bytes for each file, e.g.
+ *     // {
+ *     //     f1: 1000,
+ *     //     f2: 2000,
+ *     //     f3: 3000
+ *     // }
+ * }).catch (err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.mapValues(withMissingFileMap, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ * }).catch (err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.mapValues(fileMap, getFileSizeInBytes);
+ *         console.log(result);
+ *         // result is now a map of file size in bytes for each file, e.g.
+ *         // {
+ *         //     f1: 1000,
+ *         //     f2: 2000,
+ *         //     f3: 3000
+ *         // }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let result = await async.mapValues(withMissingFileMap, getFileSizeInBytes);
+ *         console.log(result);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function mapValues(obj, iteratee, callback) {
+  return (0, _mapValuesLimit2.default)(obj, Infinity, iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/mapValuesLimit.js b/node_modules/async/mapValuesLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..93066ee8b557460bff090f3132820fee669f28ef
--- /dev/null
+++ b/node_modules/async/mapValuesLimit.js
@@ -0,0 +1,61 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`mapValues`]{@link module:Collections.mapValues} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name mapValuesLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.mapValues]{@link module:Collections.mapValues}
+ * @category Collection
+ * @param {Object} obj - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - A function to apply to each value and key
+ * in `coll`.
+ * The iteratee should complete with the transformed value as its result.
+ * Invoked with (value, key, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. `result` is a new object consisting
+ * of each key from `obj`, with each transformed value on the right-hand side.
+ * Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function mapValuesLimit(obj, limit, iteratee, callback) {
+    callback = (0, _once2.default)(callback);
+    var newObj = {};
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+    return (0, _eachOfLimit2.default)(limit)(obj, (val, key, next) => {
+        _iteratee(val, key, (err, result) => {
+            if (err) return next(err);
+            newObj[key] = result;
+            next(err);
+        });
+    }, err => callback(err, newObj));
+}
+
+exports.default = (0, _awaitify2.default)(mapValuesLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/mapValuesSeries.js b/node_modules/async/mapValuesSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..560058aab4a46da180dd06bbdb965ed0034d27f1
--- /dev/null
+++ b/node_modules/async/mapValuesSeries.js
@@ -0,0 +1,37 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = mapValuesSeries;
+
+var _mapValuesLimit = require('./mapValuesLimit.js');
+
+var _mapValuesLimit2 = _interopRequireDefault(_mapValuesLimit);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`mapValues`]{@link module:Collections.mapValues} but runs only a single async operation at a time.
+ *
+ * @name mapValuesSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.mapValues]{@link module:Collections.mapValues}
+ * @category Collection
+ * @param {Object} obj - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - A function to apply to each value and key
+ * in `coll`.
+ * The iteratee should complete with the transformed value as its result.
+ * Invoked with (value, key, callback).
+ * @param {Function} [callback] - A callback which is called when all `iteratee`
+ * functions have finished, or an error occurs. `result` is a new object consisting
+ * of each key from `obj`, with each transformed value on the right-hand side.
+ * Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function mapValuesSeries(obj, iteratee, callback) {
+  return (0, _mapValuesLimit2.default)(obj, 1, iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/memoize.js b/node_modules/async/memoize.js
new file mode 100644
index 0000000000000000000000000000000000000000..6003e412a7d806412561e78e1a96cd1aa486a0ef
--- /dev/null
+++ b/node_modules/async/memoize.js
@@ -0,0 +1,91 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = memoize;
+
+var _setImmediate = require('./internal/setImmediate.js');
+
+var _setImmediate2 = _interopRequireDefault(_setImmediate);
+
+var _initialParams = require('./internal/initialParams.js');
+
+var _initialParams2 = _interopRequireDefault(_initialParams);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Caches the results of an async function. When creating a hash to store
+ * function results against, the callback is omitted from the hash and an
+ * optional hash function can be used.
+ *
+ * **Note: if the async function errs, the result will not be cached and
+ * subsequent calls will call the wrapped function.**
+ *
+ * If no hash function is specified, the first argument is used as a hash key,
+ * which may work reasonably if it is a string or a data type that converts to a
+ * distinct string. Note that objects and arrays will not behave reasonably.
+ * Neither will cases where the other arguments are significant. In such cases,
+ * specify your own hash function.
+ *
+ * The cache of results is exposed as the `memo` property of the function
+ * returned by `memoize`.
+ *
+ * @name memoize
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} fn - The async function to proxy and cache results from.
+ * @param {Function} hasher - An optional function for generating a custom hash
+ * for storing results. It has all the arguments applied to it apart from the
+ * callback, and must be synchronous.
+ * @returns {AsyncFunction} a memoized version of `fn`
+ * @example
+ *
+ * var slow_fn = function(name, callback) {
+ *     // do something
+ *     callback(null, result);
+ * };
+ * var fn = async.memoize(slow_fn);
+ *
+ * // fn can now be used as if it were slow_fn
+ * fn('some name', function() {
+ *     // callback
+ * });
+ */
+function memoize(fn, hasher = v => v) {
+    var memo = Object.create(null);
+    var queues = Object.create(null);
+    var _fn = (0, _wrapAsync2.default)(fn);
+    var memoized = (0, _initialParams2.default)((args, callback) => {
+        var key = hasher(...args);
+        if (key in memo) {
+            (0, _setImmediate2.default)(() => callback(null, ...memo[key]));
+        } else if (key in queues) {
+            queues[key].push(callback);
+        } else {
+            queues[key] = [callback];
+            _fn(...args, (err, ...resultArgs) => {
+                // #1465 don't memoize if an error occurred
+                if (!err) {
+                    memo[key] = resultArgs;
+                }
+                var q = queues[key];
+                delete queues[key];
+                for (var i = 0, l = q.length; i < l; i++) {
+                    q[i](err, ...resultArgs);
+                }
+            });
+        }
+    });
+    memoized.memo = memo;
+    memoized.unmemoized = fn;
+    return memoized;
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/nextTick.js b/node_modules/async/nextTick.js
new file mode 100644
index 0000000000000000000000000000000000000000..e6d321bc637a8bf89882bbf14c54f5478aeb6a79
--- /dev/null
+++ b/node_modules/async/nextTick.js
@@ -0,0 +1,52 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _setImmediate = require('./internal/setImmediate.js');
+
+/**
+ * Calls `callback` on a later loop around the event loop. In Node.js this just
+ * calls `process.nextTick`.  In the browser it will use `setImmediate` if
+ * available, otherwise `setTimeout(callback, 0)`, which means other higher
+ * priority events may precede the execution of `callback`.
+ *
+ * This is used internally for browser-compatibility purposes.
+ *
+ * @name nextTick
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @see [async.setImmediate]{@link module:Utils.setImmediate}
+ * @category Util
+ * @param {Function} callback - The function to call on a later loop around
+ * the event loop. Invoked with (args...).
+ * @param {...*} args... - any number of additional arguments to pass to the
+ * callback on the next tick.
+ * @example
+ *
+ * var call_order = [];
+ * async.nextTick(function() {
+ *     call_order.push('two');
+ *     // call_order now equals ['one','two']
+ * });
+ * call_order.push('one');
+ *
+ * async.setImmediate(function (a, b, c) {
+ *     // a, b, and c equal 1, 2, and 3
+ * }, 1, 2, 3);
+ */
+var _defer; /* istanbul ignore file */
+
+
+if (_setImmediate.hasNextTick) {
+    _defer = process.nextTick;
+} else if (_setImmediate.hasSetImmediate) {
+    _defer = setImmediate;
+} else {
+    _defer = _setImmediate.fallback;
+}
+
+exports.default = (0, _setImmediate.wrap)(_defer);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/package.json b/node_modules/async/package.json
index 1424c76cbbd7245cc71cb4c6fa8da60baed908cb..9c464bc7358793970050488097280ee55e5a7f41 100644
--- a/node_modules/async/package.json
+++ b/node_modules/async/package.json
@@ -1,15 +1,10 @@
 {
   "name": "async",
   "description": "Higher-order functions and common patterns for asynchronous code",
-  "main": "lib/async.js",
+  "version": "3.2.4",
+  "main": "dist/async.js",
   "author": "Caolan McMahon",
-  "version": "0.9.2",
-  "keywords": [
-    "async",
-    "callback",
-    "utility",
-    "module"
-  ],
+  "homepage": "https://caolan.github.io/async/",
   "repository": {
     "type": "git",
     "url": "https://github.com/caolan/async.git"
@@ -17,38 +12,64 @@
   "bugs": {
     "url": "https://github.com/caolan/async/issues"
   },
-  "license": "MIT",
+  "keywords": [
+    "async",
+    "callback",
+    "module",
+    "utility"
+  ],
   "devDependencies": {
-    "nodeunit": ">0.0.0",
-    "uglify-js": "1.2.x",
-    "nodelint": ">0.0.0",
-    "lodash": ">=2.4.1"
-  },
-  "jam": {
-    "main": "lib/async.js",
-    "include": [
-      "lib/async.js",
-      "README.md",
-      "LICENSE"
-    ],
-    "categories": [
-      "Utilities"
-    ]
+    "@babel/eslint-parser": "^7.16.5",
+    "babel-core": "^6.26.3",
+    "babel-minify": "^0.5.0",
+    "babel-plugin-add-module-exports": "^1.0.4",
+    "babel-plugin-istanbul": "^6.1.1",
+    "babel-plugin-syntax-async-generators": "^6.13.0",
+    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
+    "babel-preset-es2015": "^6.3.13",
+    "babel-preset-es2017": "^6.22.0",
+    "babel-register": "^6.26.0",
+    "babelify": "^10.0.0",
+    "benchmark": "^2.1.1",
+    "bluebird": "^3.4.6",
+    "browserify": "^17.0.0",
+    "chai": "^4.2.0",
+    "cheerio": "^0.22.0",
+    "es6-promise": "^4.2.8",
+    "eslint": "^8.6.0",
+    "eslint-plugin-prefer-arrow": "^1.2.3",
+    "fs-extra": "^10.0.0",
+    "jsdoc": "^3.6.2",
+    "karma": "^6.3.12",
+    "karma-browserify": "^8.1.0",
+    "karma-firefox-launcher": "^2.1.2",
+    "karma-mocha": "^2.0.1",
+    "karma-mocha-reporter": "^2.2.0",
+    "karma-safari-launcher": "^1.0.0",
+    "mocha": "^6.1.4",
+    "native-promise-only": "^0.8.0-a",
+    "nyc": "^15.1.0",
+    "rollup": "^2.66.1",
+    "rollup-plugin-node-resolve": "^5.2.0",
+    "rollup-plugin-npm": "^2.0.0",
+    "rsvp": "^4.8.5",
+    "semver": "^7.3.5",
+    "yargs": "^17.3.1"
   },
   "scripts": {
-    "test": "nodeunit test/test-async.js"
+    "coverage": "nyc npm run mocha-node-test -- --grep @nycinvalid --invert",
+    "jsdoc": "jsdoc -c ./support/jsdoc/jsdoc.json && node support/jsdoc/jsdoc-fix-html.js",
+    "lint": "eslint --fix .",
+    "mocha-browser-test": "karma start",
+    "mocha-node-test": "mocha",
+    "mocha-test": "npm run mocha-node-test && npm run mocha-browser-test",
+    "test": "npm run lint && npm run mocha-node-test"
   },
-  "spm": {
-    "main": "lib/async.js"
-  },
-  "volo": {
-    "main": "lib/async.js",
-    "ignore": [
-      "**/.*",
-      "node_modules",
-      "bower_components",
-      "test",
-      "tests"
+  "license": "MIT",
+  "nyc": {
+    "exclude": [
+      "test"
     ]
-  }
+  },
+  "module": "dist/async.mjs"
 }
\ No newline at end of file
diff --git a/node_modules/async/parallel.js b/node_modules/async/parallel.js
new file mode 100644
index 0000000000000000000000000000000000000000..76bc62433b68a252d1d34054a2c917cdf1208d09
--- /dev/null
+++ b/node_modules/async/parallel.js
@@ -0,0 +1,180 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = parallel;
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _parallel2 = require('./internal/parallel.js');
+
+var _parallel3 = _interopRequireDefault(_parallel2);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Run the `tasks` collection of functions in parallel, without waiting until
+ * the previous function has completed. If any of the functions pass an error to
+ * its callback, the main `callback` is immediately called with the value of the
+ * error. Once the `tasks` have completed, the results are passed to the final
+ * `callback` as an array.
+ *
+ * **Note:** `parallel` is about kicking-off I/O tasks in parallel, not about
+ * parallel execution of code.  If your tasks do not use any timers or perform
+ * any I/O, they will actually be executed in series.  Any synchronous setup
+ * sections for each task will happen one after the other.  JavaScript remains
+ * single-threaded.
+ *
+ * **Hint:** Use [`reflect`]{@link module:Utils.reflect} to continue the
+ * execution of other tasks when a task fails.
+ *
+ * It is also possible to use an object instead of an array. Each property will
+ * be run as a function and the results will be passed to the final `callback`
+ * as an object instead of an array. This can be a more readable way of handling
+ * results from {@link async.parallel}.
+ *
+ * @name parallel
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of
+ * [async functions]{@link AsyncFunction} to run.
+ * Each async function can complete with any number of optional `result` values.
+ * @param {Function} [callback] - An optional callback to run once all the
+ * functions have completed successfully. This function gets a results array
+ * (or object) containing all the result arguments passed to the task callbacks.
+ * Invoked with (err, results).
+ * @returns {Promise} a promise, if a callback is not passed
+ *
+ * @example
+ *
+ * //Using Callbacks
+ * async.parallel([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ], function(err, results) {
+ *     console.log(results);
+ *     // results is equal to ['one','two'] even though
+ *     // the second function had a shorter timeout.
+ * });
+ *
+ * // an example using an object instead of an array
+ * async.parallel({
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 1);
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 2);
+ *         }, 100);
+ *     }
+ * }, function(err, results) {
+ *     console.log(results);
+ *     // results is equal to: { one: 1, two: 2 }
+ * });
+ *
+ * //Using Promises
+ * async.parallel([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ]).then(results => {
+ *     console.log(results);
+ *     // results is equal to ['one','two'] even though
+ *     // the second function had a shorter timeout.
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // an example using an object instead of an array
+ * async.parallel({
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 1);
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 2);
+ *         }, 100);
+ *     }
+ * }).then(results => {
+ *     console.log(results);
+ *     // results is equal to: { one: 1, two: 2 }
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * //Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.parallel([
+ *             function(callback) {
+ *                 setTimeout(function() {
+ *                     callback(null, 'one');
+ *                 }, 200);
+ *             },
+ *             function(callback) {
+ *                 setTimeout(function() {
+ *                     callback(null, 'two');
+ *                 }, 100);
+ *             }
+ *         ]);
+ *         console.log(results);
+ *         // results is equal to ['one','two'] even though
+ *         // the second function had a shorter timeout.
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // an example using an object instead of an array
+ * async () => {
+ *     try {
+ *         let results = await async.parallel({
+ *             one: function(callback) {
+ *                 setTimeout(function() {
+ *                     callback(null, 1);
+ *                 }, 200);
+ *             },
+ *            two: function(callback) {
+ *                 setTimeout(function() {
+ *                     callback(null, 2);
+ *                 }, 100);
+ *            }
+ *         });
+ *         console.log(results);
+ *         // results is equal to: { one: 1, two: 2 }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function parallel(tasks, callback) {
+  return (0, _parallel3.default)(_eachOf2.default, tasks, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/parallelLimit.js b/node_modules/async/parallelLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..dbe0bb8cc8b27ab4edaad39487bb6617ce123314
--- /dev/null
+++ b/node_modules/async/parallelLimit.js
@@ -0,0 +1,41 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = parallelLimit;
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _parallel = require('./internal/parallel.js');
+
+var _parallel2 = _interopRequireDefault(_parallel);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`parallel`]{@link module:ControlFlow.parallel} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name parallelLimit
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.parallel]{@link module:ControlFlow.parallel}
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection of
+ * [async functions]{@link AsyncFunction} to run.
+ * Each async function can complete with any number of optional `result` values.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {Function} [callback] - An optional callback to run once all the
+ * functions have completed successfully. This function gets a results array
+ * (or object) containing all the result arguments passed to the task callbacks.
+ * Invoked with (err, results).
+ * @returns {Promise} a promise, if a callback is not passed
+ */
+function parallelLimit(tasks, limit, callback) {
+  return (0, _parallel2.default)((0, _eachOfLimit2.default)(limit), tasks, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/priorityQueue.js b/node_modules/async/priorityQueue.js
new file mode 100644
index 0000000000000000000000000000000000000000..6006f669d66843894467fb96ecf6824ebdbe6840
--- /dev/null
+++ b/node_modules/async/priorityQueue.js
@@ -0,0 +1,86 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+exports.default = function (worker, concurrency) {
+    // Start with a normal queue
+    var q = (0, _queue2.default)(worker, concurrency);
+
+    var {
+        push,
+        pushAsync
+    } = q;
+
+    q._tasks = new _Heap2.default();
+    q._createTaskItem = ({ data, priority }, callback) => {
+        return {
+            data,
+            priority,
+            callback
+        };
+    };
+
+    function createDataItems(tasks, priority) {
+        if (!Array.isArray(tasks)) {
+            return { data: tasks, priority };
+        }
+        return tasks.map(data => {
+            return { data, priority };
+        });
+    }
+
+    // Override push to accept second parameter representing priority
+    q.push = function (data, priority = 0, callback) {
+        return push(createDataItems(data, priority), callback);
+    };
+
+    q.pushAsync = function (data, priority = 0, callback) {
+        return pushAsync(createDataItems(data, priority), callback);
+    };
+
+    // Remove unshift functions
+    delete q.unshift;
+    delete q.unshiftAsync;
+
+    return q;
+};
+
+var _queue = require('./queue.js');
+
+var _queue2 = _interopRequireDefault(_queue);
+
+var _Heap = require('./internal/Heap.js');
+
+var _Heap2 = _interopRequireDefault(_Heap);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+module.exports = exports['default'];
+
+/**
+ * The same as [async.queue]{@link module:ControlFlow.queue} only tasks are assigned a priority and
+ * completed in ascending priority order.
+ *
+ * @name priorityQueue
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.queue]{@link module:ControlFlow.queue}
+ * @category Control Flow
+ * @param {AsyncFunction} worker - An async function for processing a queued task.
+ * If you want to handle errors from an individual task, pass a callback to
+ * `q.push()`.
+ * Invoked with (task, callback).
+ * @param {number} concurrency - An `integer` for determining how many `worker`
+ * functions should be run in parallel.  If omitted, the concurrency defaults to
+ * `1`.  If the concurrency is `0`, an error is thrown.
+ * @returns {module:ControlFlow.QueueObject} A priorityQueue object to manage the tasks. There are three
+ * differences between `queue` and `priorityQueue` objects:
+ * * `push(task, priority, [callback])` - `priority` should be a number. If an
+ *   array of `tasks` is given, all tasks will be assigned the same priority.
+ * * `pushAsync(task, priority, [callback])` - the same as `priorityQueue.push`,
+ *   except this returns a promise that rejects if an error occurs.
+ * * The `unshift` and `unshiftAsync` methods were removed.
+ */
\ No newline at end of file
diff --git a/node_modules/async/queue.js b/node_modules/async/queue.js
new file mode 100644
index 0000000000000000000000000000000000000000..c69becb8caf751bf99ff105bdbb5de362add38c2
--- /dev/null
+++ b/node_modules/async/queue.js
@@ -0,0 +1,167 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+exports.default = function (worker, concurrency) {
+  var _worker = (0, _wrapAsync2.default)(worker);
+  return (0, _queue2.default)((items, cb) => {
+    _worker(items[0], cb);
+  }, concurrency, 1);
+};
+
+var _queue = require('./internal/queue.js');
+
+var _queue2 = _interopRequireDefault(_queue);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+module.exports = exports['default'];
+
+/**
+ * A queue of tasks for the worker function to complete.
+ * @typedef {Iterable} QueueObject
+ * @memberOf module:ControlFlow
+ * @property {Function} length - a function returning the number of items
+ * waiting to be processed. Invoke with `queue.length()`.
+ * @property {boolean} started - a boolean indicating whether or not any
+ * items have been pushed and processed by the queue.
+ * @property {Function} running - a function returning the number of items
+ * currently being processed. Invoke with `queue.running()`.
+ * @property {Function} workersList - a function returning the array of items
+ * currently being processed. Invoke with `queue.workersList()`.
+ * @property {Function} idle - a function returning false if there are items
+ * waiting or being processed, or true if not. Invoke with `queue.idle()`.
+ * @property {number} concurrency - an integer for determining how many `worker`
+ * functions should be run in parallel. This property can be changed after a
+ * `queue` is created to alter the concurrency on-the-fly.
+ * @property {number} payload - an integer that specifies how many items are
+ * passed to the worker function at a time. only applies if this is a
+ * [cargo]{@link module:ControlFlow.cargo} object
+ * @property {AsyncFunction} push - add a new task to the `queue`. Calls `callback`
+ * once the `worker` has finished processing the task. Instead of a single task,
+ * a `tasks` array can be submitted. The respective callback is used for every
+ * task in the list. Invoke with `queue.push(task, [callback])`,
+ * @property {AsyncFunction} unshift - add a new task to the front of the `queue`.
+ * Invoke with `queue.unshift(task, [callback])`.
+ * @property {AsyncFunction} pushAsync - the same as `q.push`, except this returns
+ * a promise that rejects if an error occurs.
+ * @property {AsyncFunction} unshiftAsync - the same as `q.unshift`, except this returns
+ * a promise that rejects if an error occurs.
+ * @property {Function} remove - remove items from the queue that match a test
+ * function.  The test function will be passed an object with a `data` property,
+ * and a `priority` property, if this is a
+ * [priorityQueue]{@link module:ControlFlow.priorityQueue} object.
+ * Invoked with `queue.remove(testFn)`, where `testFn` is of the form
+ * `function ({data, priority}) {}` and returns a Boolean.
+ * @property {Function} saturated - a function that sets a callback that is
+ * called when the number of running workers hits the `concurrency` limit, and
+ * further tasks will be queued.  If the callback is omitted, `q.saturated()`
+ * returns a promise for the next occurrence.
+ * @property {Function} unsaturated - a function that sets a callback that is
+ * called when the number of running workers is less than the `concurrency` &
+ * `buffer` limits, and further tasks will not be queued. If the callback is
+ * omitted, `q.unsaturated()` returns a promise for the next occurrence.
+ * @property {number} buffer - A minimum threshold buffer in order to say that
+ * the `queue` is `unsaturated`.
+ * @property {Function} empty - a function that sets a callback that is called
+ * when the last item from the `queue` is given to a `worker`. If the callback
+ * is omitted, `q.empty()` returns a promise for the next occurrence.
+ * @property {Function} drain - a function that sets a callback that is called
+ * when the last item from the `queue` has returned from the `worker`. If the
+ * callback is omitted, `q.drain()` returns a promise for the next occurrence.
+ * @property {Function} error - a function that sets a callback that is called
+ * when a task errors. Has the signature `function(error, task)`. If the
+ * callback is omitted, `error()` returns a promise that rejects on the next
+ * error.
+ * @property {boolean} paused - a boolean for determining whether the queue is
+ * in a paused state.
+ * @property {Function} pause - a function that pauses the processing of tasks
+ * until `resume()` is called. Invoke with `queue.pause()`.
+ * @property {Function} resume - a function that resumes the processing of
+ * queued tasks when the queue is paused. Invoke with `queue.resume()`.
+ * @property {Function} kill - a function that removes the `drain` callback and
+ * empties remaining tasks from the queue forcing it to go idle. No more tasks
+ * should be pushed to the queue after calling this function. Invoke with `queue.kill()`.
+ *
+ * @example
+ * const q = async.queue(worker, 2)
+ * q.push(item1)
+ * q.push(item2)
+ * q.push(item3)
+ * // queues are iterable, spread into an array to inspect
+ * const items = [...q] // [item1, item2, item3]
+ * // or use for of
+ * for (let item of q) {
+ *     console.log(item)
+ * }
+ *
+ * q.drain(() => {
+ *     console.log('all done')
+ * })
+ * // or
+ * await q.drain()
+ */
+
+/**
+ * Creates a `queue` object with the specified `concurrency`. Tasks added to the
+ * `queue` are processed in parallel (up to the `concurrency` limit). If all
+ * `worker`s are in progress, the task is queued until one becomes available.
+ * Once a `worker` completes a `task`, that `task`'s callback is called.
+ *
+ * @name queue
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {AsyncFunction} worker - An async function for processing a queued task.
+ * If you want to handle errors from an individual task, pass a callback to
+ * `q.push()`. Invoked with (task, callback).
+ * @param {number} [concurrency=1] - An `integer` for determining how many
+ * `worker` functions should be run in parallel.  If omitted, the concurrency
+ * defaults to `1`.  If the concurrency is `0`, an error is thrown.
+ * @returns {module:ControlFlow.QueueObject} A queue object to manage the tasks. Callbacks can be
+ * attached as certain properties to listen for specific events during the
+ * lifecycle of the queue.
+ * @example
+ *
+ * // create a queue object with concurrency 2
+ * var q = async.queue(function(task, callback) {
+ *     console.log('hello ' + task.name);
+ *     callback();
+ * }, 2);
+ *
+ * // assign a callback
+ * q.drain(function() {
+ *     console.log('all items have been processed');
+ * });
+ * // or await the end
+ * await q.drain()
+ *
+ * // assign an error callback
+ * q.error(function(err, task) {
+ *     console.error('task experienced an error');
+ * });
+ *
+ * // add some items to the queue
+ * q.push({name: 'foo'}, function(err) {
+ *     console.log('finished processing foo');
+ * });
+ * // callback is optional
+ * q.push({name: 'bar'});
+ *
+ * // add some items to the queue (batch-wise)
+ * q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
+ *     console.log('finished processing item');
+ * });
+ *
+ * // add some items to the front of the queue
+ * q.unshift({name: 'bar'}, function (err) {
+ *     console.log('finished processing bar');
+ * });
+ */
\ No newline at end of file
diff --git a/node_modules/async/race.js b/node_modules/async/race.js
new file mode 100644
index 0000000000000000000000000000000000000000..9595d884925272328bf5e13cc2042714020ebd00
--- /dev/null
+++ b/node_modules/async/race.js
@@ -0,0 +1,67 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Runs the `tasks` array of functions in parallel, without waiting until the
+ * previous function has completed. Once any of the `tasks` complete or pass an
+ * error to its callback, the main `callback` is immediately called. It's
+ * equivalent to `Promise.race()`.
+ *
+ * @name race
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array} tasks - An array containing [async functions]{@link AsyncFunction}
+ * to run. Each function can complete with an optional `result` value.
+ * @param {Function} callback - A callback to run once any of the functions have
+ * completed. This function gets an error or result from the first function that
+ * completed. Invoked with (err, result).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * async.race([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ],
+ * // main callback
+ * function(err, result) {
+ *     // the result will be equal to 'two' as it finishes earlier
+ * });
+ */
+function race(tasks, callback) {
+    callback = (0, _once2.default)(callback);
+    if (!Array.isArray(tasks)) return callback(new TypeError('First argument to race must be an array of functions'));
+    if (!tasks.length) return callback();
+    for (var i = 0, l = tasks.length; i < l; i++) {
+        (0, _wrapAsync2.default)(tasks[i])(callback);
+    }
+}
+
+exports.default = (0, _awaitify2.default)(race, 2);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/reduce.js b/node_modules/async/reduce.js
new file mode 100644
index 0000000000000000000000000000000000000000..56e2db8139e7ba84cf39981a107b841604673043
--- /dev/null
+++ b/node_modules/async/reduce.js
@@ -0,0 +1,153 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Reduces `coll` into a single value using an async `iteratee` to return each
+ * successive step. `memo` is the initial state of the reduction. This function
+ * only operates in series.
+ *
+ * For performance reasons, it may make sense to split a call to this function
+ * into a parallel map, and then use the normal `Array.prototype.reduce` on the
+ * results. This function is for situations where each step in the reduction
+ * needs to be async; if you can get the data before reducing it, then it's
+ * probably a good idea to do so.
+ *
+ * @name reduce
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias inject
+ * @alias foldl
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {*} memo - The initial state of the reduction.
+ * @param {AsyncFunction} iteratee - A function applied to each item in the
+ * array to produce the next step in the reduction.
+ * The `iteratee` should complete with the next state of the reduction.
+ * If the iteratee completes with an error, the reduction is stopped and the
+ * main `callback` is immediately called with the error.
+ * Invoked with (memo, item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result is the reduced value. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ * // file4.txt does not exist
+ *
+ * const fileList = ['file1.txt','file2.txt','file3.txt'];
+ * const withMissingFileList = ['file1.txt','file2.txt','file3.txt', 'file4.txt'];
+ *
+ * // asynchronous function that computes the file size in bytes
+ * // file size is added to the memoized value, then returned
+ * function getFileSizeInBytes(memo, file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, memo + stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.reduce(fileList, 0, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // 6000
+ *         // which is the sum of the file sizes of the three files
+ *     }
+ * });
+ *
+ * // Error Handling
+ * async.reduce(withMissingFileList, 0, getFileSizeInBytes, function(err, result) {
+ *     if (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     } else {
+ *         console.log(result);
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.reduce(fileList, 0, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ *     // 6000
+ *     // which is the sum of the file sizes of the three files
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error Handling
+ * async.reduce(withMissingFileList, 0, getFileSizeInBytes)
+ * .then( result => {
+ *     console.log(result);
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.reduce(fileList, 0, getFileSizeInBytes);
+ *         console.log(result);
+ *         // 6000
+ *         // which is the sum of the file sizes of the three files
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // Error Handling
+ * async () => {
+ *     try {
+ *         let result = await async.reduce(withMissingFileList, 0, getFileSizeInBytes);
+ *         console.log(result);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function reduce(coll, memo, iteratee, callback) {
+    callback = (0, _once2.default)(callback);
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+    return (0, _eachOfSeries2.default)(coll, (x, i, iterCb) => {
+        _iteratee(memo, x, (err, v) => {
+            memo = v;
+            iterCb(err);
+        });
+    }, err => callback(err, memo));
+}
+exports.default = (0, _awaitify2.default)(reduce, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/reduceRight.js b/node_modules/async/reduceRight.js
new file mode 100644
index 0000000000000000000000000000000000000000..bee5391d31431a9264ac1a3d435aaee0499941f6
--- /dev/null
+++ b/node_modules/async/reduceRight.js
@@ -0,0 +1,41 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = reduceRight;
+
+var _reduce = require('./reduce.js');
+
+var _reduce2 = _interopRequireDefault(_reduce);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Same as [`reduce`]{@link module:Collections.reduce}, only operates on `array` in reverse order.
+ *
+ * @name reduceRight
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.reduce]{@link module:Collections.reduce}
+ * @alias foldr
+ * @category Collection
+ * @param {Array} array - A collection to iterate over.
+ * @param {*} memo - The initial state of the reduction.
+ * @param {AsyncFunction} iteratee - A function applied to each item in the
+ * array to produce the next step in the reduction.
+ * The `iteratee` should complete with the next state of the reduction.
+ * If the iteratee completes with an error, the reduction is stopped and the
+ * main `callback` is immediately called with the error.
+ * Invoked with (memo, item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result is the reduced value. Invoked with
+ * (err, result).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function reduceRight(array, memo, iteratee, callback) {
+  var reversed = [...array].reverse();
+  return (0, _reduce2.default)(reversed, memo, iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/reflect.js b/node_modules/async/reflect.js
new file mode 100644
index 0000000000000000000000000000000000000000..297ed797172bc8187fe013aeadd21da2b08c3876
--- /dev/null
+++ b/node_modules/async/reflect.js
@@ -0,0 +1,78 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = reflect;
+
+var _initialParams = require('./internal/initialParams.js');
+
+var _initialParams2 = _interopRequireDefault(_initialParams);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Wraps the async function in another function that always completes with a
+ * result object, even when it errors.
+ *
+ * The result object has either the property `error` or `value`.
+ *
+ * @name reflect
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} fn - The async function you want to wrap
+ * @returns {Function} - A function that always passes null to it's callback as
+ * the error. The second argument to the callback will be an `object` with
+ * either an `error` or a `value` property.
+ * @example
+ *
+ * async.parallel([
+ *     async.reflect(function(callback) {
+ *         // do some stuff ...
+ *         callback(null, 'one');
+ *     }),
+ *     async.reflect(function(callback) {
+ *         // do some more stuff but error ...
+ *         callback('bad stuff happened');
+ *     }),
+ *     async.reflect(function(callback) {
+ *         // do some more stuff ...
+ *         callback(null, 'two');
+ *     })
+ * ],
+ * // optional callback
+ * function(err, results) {
+ *     // values
+ *     // results[0].value = 'one'
+ *     // results[1].error = 'bad stuff happened'
+ *     // results[2].value = 'two'
+ * });
+ */
+function reflect(fn) {
+    var _fn = (0, _wrapAsync2.default)(fn);
+    return (0, _initialParams2.default)(function reflectOn(args, reflectCallback) {
+        args.push((error, ...cbArgs) => {
+            let retVal = {};
+            if (error) {
+                retVal.error = error;
+            }
+            if (cbArgs.length > 0) {
+                var value = cbArgs;
+                if (cbArgs.length <= 1) {
+                    [value] = cbArgs;
+                }
+                retVal.value = value;
+            }
+            reflectCallback(null, retVal);
+        });
+
+        return _fn.apply(this, args);
+    });
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/reflectAll.js b/node_modules/async/reflectAll.js
new file mode 100644
index 0000000000000000000000000000000000000000..a862ff050f10162876073cfefee9472e406b4507
--- /dev/null
+++ b/node_modules/async/reflectAll.js
@@ -0,0 +1,93 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = reflectAll;
+
+var _reflect = require('./reflect.js');
+
+var _reflect2 = _interopRequireDefault(_reflect);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * A helper function that wraps an array or an object of functions with `reflect`.
+ *
+ * @name reflectAll
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @see [async.reflect]{@link module:Utils.reflect}
+ * @category Util
+ * @param {Array|Object|Iterable} tasks - The collection of
+ * [async functions]{@link AsyncFunction} to wrap in `async.reflect`.
+ * @returns {Array} Returns an array of async functions, each wrapped in
+ * `async.reflect`
+ * @example
+ *
+ * let tasks = [
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         // do some more stuff but error ...
+ *         callback(new Error('bad stuff happened'));
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ];
+ *
+ * async.parallel(async.reflectAll(tasks),
+ * // optional callback
+ * function(err, results) {
+ *     // values
+ *     // results[0].value = 'one'
+ *     // results[1].error = Error('bad stuff happened')
+ *     // results[2].value = 'two'
+ * });
+ *
+ * // an example using an object instead of an array
+ * let tasks = {
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         callback('two');
+ *     },
+ *     three: function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'three');
+ *         }, 100);
+ *     }
+ * };
+ *
+ * async.parallel(async.reflectAll(tasks),
+ * // optional callback
+ * function(err, results) {
+ *     // values
+ *     // results.one.value = 'one'
+ *     // results.two.error = 'two'
+ *     // results.three.value = 'three'
+ * });
+ */
+function reflectAll(tasks) {
+    var results;
+    if (Array.isArray(tasks)) {
+        results = tasks.map(_reflect2.default);
+    } else {
+        results = {};
+        Object.keys(tasks).forEach(key => {
+            results[key] = _reflect2.default.call(this, tasks[key]);
+        });
+    }
+    return results;
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/reject.js b/node_modules/async/reject.js
new file mode 100644
index 0000000000000000000000000000000000000000..cabd96ea0869e01afde0202a98b382bbf33f0139
--- /dev/null
+++ b/node_modules/async/reject.js
@@ -0,0 +1,87 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _reject2 = require('./internal/reject.js');
+
+var _reject3 = _interopRequireDefault(_reject2);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The opposite of [`filter`]{@link module:Collections.filter}. Removes values that pass an `async` truth test.
+ *
+ * @name reject
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.filter]{@link module:Collections.filter}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - An async truth test to apply to each item in
+ * `coll`.
+ * The should complete with a boolean value as its `result`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ *
+ * const fileList = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt'];
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.reject(fileList, fileExists, function(err, results) {
+ *    // [ 'dir3/file6.txt' ]
+ *    // results now equals an array of the non-existing files
+ * });
+ *
+ * // Using Promises
+ * async.reject(fileList, fileExists)
+ * .then( results => {
+ *     console.log(results);
+ *     // [ 'dir3/file6.txt' ]
+ *     // results now equals an array of the non-existing files
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.reject(fileList, fileExists);
+ *         console.log(results);
+ *         // [ 'dir3/file6.txt' ]
+ *         // results now equals an array of the non-existing files
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function reject(coll, iteratee, callback) {
+  return (0, _reject3.default)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(reject, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/rejectLimit.js b/node_modules/async/rejectLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..1a899252e10f4508f3abf239709dc440023f5a77
--- /dev/null
+++ b/node_modules/async/rejectLimit.js
@@ -0,0 +1,45 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _reject2 = require('./internal/reject.js');
+
+var _reject3 = _interopRequireDefault(_reject2);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`reject`]{@link module:Collections.reject} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name rejectLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.reject]{@link module:Collections.reject}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {Function} iteratee - An async truth test to apply to each item in
+ * `coll`.
+ * The should complete with a boolean value as its `result`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function rejectLimit(coll, limit, iteratee, callback) {
+  return (0, _reject3.default)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(rejectLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/rejectSeries.js b/node_modules/async/rejectSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e1a1c5e3ee0844c832fd7850261bd29d6818d6b
--- /dev/null
+++ b/node_modules/async/rejectSeries.js
@@ -0,0 +1,43 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _reject2 = require('./internal/reject.js');
+
+var _reject3 = _interopRequireDefault(_reject2);
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`reject`]{@link module:Collections.reject} but runs only a single async operation at a time.
+ *
+ * @name rejectSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.reject]{@link module:Collections.reject}
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - An async truth test to apply to each item in
+ * `coll`.
+ * The should complete with a boolean value as its `result`.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ */
+function rejectSeries(coll, iteratee, callback) {
+  return (0, _reject3.default)(_eachOfSeries2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(rejectSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/retry.js b/node_modules/async/retry.js
new file mode 100644
index 0000000000000000000000000000000000000000..dba303016557db80e816a0315c942d44435d14f3
--- /dev/null
+++ b/node_modules/async/retry.js
@@ -0,0 +1,159 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = retry;
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _promiseCallback = require('./internal/promiseCallback.js');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function constant(value) {
+    return function () {
+        return value;
+    };
+}
+
+/**
+ * Attempts to get a successful response from `task` no more than `times` times
+ * before returning an error. If the task is successful, the `callback` will be
+ * passed the result of the successful task. If all attempts fail, the callback
+ * will be passed the error and result (if any) of the final attempt.
+ *
+ * @name retry
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @see [async.retryable]{@link module:ControlFlow.retryable}
+ * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - Can be either an
+ * object with `times` and `interval` or a number.
+ * * `times` - The number of attempts to make before giving up.  The default
+ *   is `5`.
+ * * `interval` - The time to wait between retries, in milliseconds.  The
+ *   default is `0`. The interval may also be specified as a function of the
+ *   retry count (see example).
+ * * `errorFilter` - An optional synchronous function that is invoked on
+ *   erroneous result. If it returns `true` the retry attempts will continue;
+ *   if the function returns `false` the retry flow is aborted with the current
+ *   attempt's error and result being returned to the final callback.
+ *   Invoked with (err).
+ * * If `opts` is a number, the number specifies the number of times to retry,
+ *   with the default interval of `0`.
+ * @param {AsyncFunction} task - An async function to retry.
+ * Invoked with (callback).
+ * @param {Function} [callback] - An optional callback which is called when the
+ * task has succeeded, or after the final failed attempt. It receives the `err`
+ * and `result` arguments of the last attempt at completing the `task`. Invoked
+ * with (err, results).
+ * @returns {Promise} a promise if no callback provided
+ *
+ * @example
+ *
+ * // The `retry` function can be used as a stand-alone control flow by passing
+ * // a callback, as shown below:
+ *
+ * // try calling apiMethod 3 times
+ * async.retry(3, apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // try calling apiMethod 3 times, waiting 200 ms between each retry
+ * async.retry({times: 3, interval: 200}, apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // try calling apiMethod 10 times with exponential backoff
+ * // (i.e. intervals of 100, 200, 400, 800, 1600, ... milliseconds)
+ * async.retry({
+ *   times: 10,
+ *   interval: function(retryCount) {
+ *     return 50 * Math.pow(2, retryCount);
+ *   }
+ * }, apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // try calling apiMethod the default 5 times no delay between each retry
+ * async.retry(apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // try calling apiMethod only when error condition satisfies, all other
+ * // errors will abort the retry control flow and return to final callback
+ * async.retry({
+ *   errorFilter: function(err) {
+ *     return err.message === 'Temporary error'; // only retry on a specific error
+ *   }
+ * }, apiMethod, function(err, result) {
+ *     // do something with the result
+ * });
+ *
+ * // to retry individual methods that are not as reliable within other
+ * // control flow functions, use the `retryable` wrapper:
+ * async.auto({
+ *     users: api.getUsers.bind(api),
+ *     payments: async.retryable(3, api.getPayments.bind(api))
+ * }, function(err, results) {
+ *     // do something with the results
+ * });
+ *
+ */
+const DEFAULT_TIMES = 5;
+const DEFAULT_INTERVAL = 0;
+
+function retry(opts, task, callback) {
+    var options = {
+        times: DEFAULT_TIMES,
+        intervalFunc: constant(DEFAULT_INTERVAL)
+    };
+
+    if (arguments.length < 3 && typeof opts === 'function') {
+        callback = task || (0, _promiseCallback.promiseCallback)();
+        task = opts;
+    } else {
+        parseTimes(options, opts);
+        callback = callback || (0, _promiseCallback.promiseCallback)();
+    }
+
+    if (typeof task !== 'function') {
+        throw new Error("Invalid arguments for async.retry");
+    }
+
+    var _task = (0, _wrapAsync2.default)(task);
+
+    var attempt = 1;
+    function retryAttempt() {
+        _task((err, ...args) => {
+            if (err === false) return;
+            if (err && attempt++ < options.times && (typeof options.errorFilter != 'function' || options.errorFilter(err))) {
+                setTimeout(retryAttempt, options.intervalFunc(attempt - 1));
+            } else {
+                callback(err, ...args);
+            }
+        });
+    }
+
+    retryAttempt();
+    return callback[_promiseCallback.PROMISE_SYMBOL];
+}
+
+function parseTimes(acc, t) {
+    if (typeof t === 'object') {
+        acc.times = +t.times || DEFAULT_TIMES;
+
+        acc.intervalFunc = typeof t.interval === 'function' ? t.interval : constant(+t.interval || DEFAULT_INTERVAL);
+
+        acc.errorFilter = t.errorFilter;
+    } else if (typeof t === 'number' || typeof t === 'string') {
+        acc.times = +t || DEFAULT_TIMES;
+    } else {
+        throw new Error("Invalid arguments for async.retry");
+    }
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/retryable.js b/node_modules/async/retryable.js
new file mode 100644
index 0000000000000000000000000000000000000000..1b1147cd6f38ff590556590058a1d6c74cce3edf
--- /dev/null
+++ b/node_modules/async/retryable.js
@@ -0,0 +1,77 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = retryable;
+
+var _retry = require('./retry.js');
+
+var _retry2 = _interopRequireDefault(_retry);
+
+var _initialParams = require('./internal/initialParams.js');
+
+var _initialParams2 = _interopRequireDefault(_initialParams);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _promiseCallback = require('./internal/promiseCallback.js');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * A close relative of [`retry`]{@link module:ControlFlow.retry}.  This method
+ * wraps a task and makes it retryable, rather than immediately calling it
+ * with retries.
+ *
+ * @name retryable
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.retry]{@link module:ControlFlow.retry}
+ * @category Control Flow
+ * @param {Object|number} [opts = {times: 5, interval: 0}| 5] - optional
+ * options, exactly the same as from `retry`, except for a `opts.arity` that
+ * is the arity of the `task` function, defaulting to `task.length`
+ * @param {AsyncFunction} task - the asynchronous function to wrap.
+ * This function will be passed any arguments passed to the returned wrapper.
+ * Invoked with (...args, callback).
+ * @returns {AsyncFunction} The wrapped function, which when invoked, will
+ * retry on an error, based on the parameters specified in `opts`.
+ * This function will accept the same parameters as `task`.
+ * @example
+ *
+ * async.auto({
+ *     dep1: async.retryable(3, getFromFlakyService),
+ *     process: ["dep1", async.retryable(3, function (results, cb) {
+ *         maybeProcessData(results.dep1, cb);
+ *     })]
+ * }, callback);
+ */
+function retryable(opts, task) {
+    if (!task) {
+        task = opts;
+        opts = null;
+    }
+    let arity = opts && opts.arity || task.length;
+    if ((0, _wrapAsync.isAsync)(task)) {
+        arity += 1;
+    }
+    var _task = (0, _wrapAsync2.default)(task);
+    return (0, _initialParams2.default)((args, callback) => {
+        if (args.length < arity - 1 || callback == null) {
+            args.push(callback);
+            callback = (0, _promiseCallback.promiseCallback)();
+        }
+        function taskFn(cb) {
+            _task(...args, cb);
+        }
+
+        if (opts) (0, _retry2.default)(opts, taskFn, callback);else (0, _retry2.default)(taskFn, callback);
+
+        return callback[_promiseCallback.PROMISE_SYMBOL];
+    });
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/select.js b/node_modules/async/select.js
new file mode 100644
index 0000000000000000000000000000000000000000..303dc1fb92b87c9f8e084e1d2d50a85f18262f88
--- /dev/null
+++ b/node_modules/async/select.js
@@ -0,0 +1,93 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _filter2 = require('./internal/filter.js');
+
+var _filter3 = _interopRequireDefault(_filter2);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Returns a new array of all the values in `coll` which pass an async truth
+ * test. This operation is performed in parallel, but the results array will be
+ * in the same order as the original.
+ *
+ * @name filter
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias select
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+ * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+ * with a boolean argument once it has completed. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ *
+ * const files = ['dir1/file1.txt','dir2/file3.txt','dir3/file6.txt'];
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.filter(files, fileExists, function(err, results) {
+ *    if(err) {
+ *        console.log(err);
+ *    } else {
+ *        console.log(results);
+ *        // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+ *        // results is now an array of the existing files
+ *    }
+ * });
+ *
+ * // Using Promises
+ * async.filter(files, fileExists)
+ * .then(results => {
+ *     console.log(results);
+ *     // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+ *     // results is now an array of the existing files
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.filter(files, fileExists);
+ *         console.log(results);
+ *         // [ 'dir1/file1.txt', 'dir2/file3.txt' ]
+ *         // results is now an array of the existing files
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function filter(coll, iteratee, callback) {
+  return (0, _filter3.default)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(filter, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/selectLimit.js b/node_modules/async/selectLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..89e55f539ade5fd9744289c0bfbc02fed7e8c79f
--- /dev/null
+++ b/node_modules/async/selectLimit.js
@@ -0,0 +1,45 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _filter2 = require('./internal/filter.js');
+
+var _filter3 = _interopRequireDefault(_filter2);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`filter`]{@link module:Collections.filter} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name filterLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.filter]{@link module:Collections.filter}
+ * @alias selectLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+ * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+ * with a boolean argument once it has completed. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function filterLimit(coll, limit, iteratee, callback) {
+  return (0, _filter3.default)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(filterLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/selectSeries.js b/node_modules/async/selectSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..a045e52c5a4890dd8c326e6c50a5f363192a4aca
--- /dev/null
+++ b/node_modules/async/selectSeries.js
@@ -0,0 +1,43 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _filter2 = require('./internal/filter.js');
+
+var _filter3 = _interopRequireDefault(_filter2);
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`filter`]{@link module:Collections.filter} but runs only a single async operation at a time.
+ *
+ * @name filterSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.filter]{@link module:Collections.filter}
+ * @alias selectSeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {Function} iteratee - A truth test to apply to each item in `coll`.
+ * The `iteratee` is passed a `callback(err, truthValue)`, which must be called
+ * with a boolean argument once it has completed. Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Invoked with (err, results)
+ * @returns {Promise} a promise, if no callback provided
+ */
+function filterSeries(coll, iteratee, callback) {
+  return (0, _filter3.default)(_eachOfSeries2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(filterSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/seq.js b/node_modules/async/seq.js
new file mode 100644
index 0000000000000000000000000000000000000000..28c825f2a7f89b53d0789a9496099e30ac3fe35c
--- /dev/null
+++ b/node_modules/async/seq.js
@@ -0,0 +1,79 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = seq;
+
+var _reduce = require('./reduce.js');
+
+var _reduce2 = _interopRequireDefault(_reduce);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _promiseCallback = require('./internal/promiseCallback.js');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Version of the compose function that is more natural to read. Each function
+ * consumes the return value of the previous function. It is the equivalent of
+ * [compose]{@link module:ControlFlow.compose} with the arguments reversed.
+ *
+ * Each function is executed with the `this` binding of the composed function.
+ *
+ * @name seq
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.compose]{@link module:ControlFlow.compose}
+ * @category Control Flow
+ * @param {...AsyncFunction} functions - the asynchronous functions to compose
+ * @returns {Function} a function that composes the `functions` in order
+ * @example
+ *
+ * // Requires lodash (or underscore), express3 and dresende's orm2.
+ * // Part of an app, that fetches cats of the logged user.
+ * // This example uses `seq` function to avoid overnesting and error
+ * // handling clutter.
+ * app.get('/cats', function(request, response) {
+ *     var User = request.models.User;
+ *     async.seq(
+ *         User.get.bind(User),  // 'User.get' has signature (id, callback(err, data))
+ *         function(user, fn) {
+ *             user.getCats(fn);      // 'getCats' has signature (callback(err, data))
+ *         }
+ *     )(req.session.user_id, function (err, cats) {
+ *         if (err) {
+ *             console.error(err);
+ *             response.json({ status: 'error', message: err.message });
+ *         } else {
+ *             response.json({ status: 'ok', message: 'Cats found', data: cats });
+ *         }
+ *     });
+ * });
+ */
+function seq(...functions) {
+    var _functions = functions.map(_wrapAsync2.default);
+    return function (...args) {
+        var that = this;
+
+        var cb = args[args.length - 1];
+        if (typeof cb == 'function') {
+            args.pop();
+        } else {
+            cb = (0, _promiseCallback.promiseCallback)();
+        }
+
+        (0, _reduce2.default)(_functions, args, (newargs, fn, iterCb) => {
+            fn.apply(that, newargs.concat((err, ...nextargs) => {
+                iterCb(err, nextargs);
+            }));
+        }, (err, results) => cb(err, ...results));
+
+        return cb[_promiseCallback.PROMISE_SYMBOL];
+    };
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/series.js b/node_modules/async/series.js
new file mode 100644
index 0000000000000000000000000000000000000000..56e78f9fb8daf3b10c37baf206cc9dd4a492cbbf
--- /dev/null
+++ b/node_modules/async/series.js
@@ -0,0 +1,186 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = series;
+
+var _parallel2 = require('./internal/parallel.js');
+
+var _parallel3 = _interopRequireDefault(_parallel2);
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Run the functions in the `tasks` collection in series, each one running once
+ * the previous function has completed. If any functions in the series pass an
+ * error to its callback, no more functions are run, and `callback` is
+ * immediately called with the value of the error. Otherwise, `callback`
+ * receives an array of results when `tasks` have completed.
+ *
+ * It is also possible to use an object instead of an array. Each property will
+ * be run as a function, and the results will be passed to the final `callback`
+ * as an object instead of an array. This can be a more readable way of handling
+ *  results from {@link async.series}.
+ *
+ * **Note** that while many implementations preserve the order of object
+ * properties, the [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/5.1/#sec-8.6)
+ * explicitly states that
+ *
+ * > The mechanics and order of enumerating the properties is not specified.
+ *
+ * So if you rely on the order in which your series of functions are executed,
+ * and want this to work on all platforms, consider using an array.
+ *
+ * @name series
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing
+ * [async functions]{@link AsyncFunction} to run in series.
+ * Each function can complete with any number of optional `result` values.
+ * @param {Function} [callback] - An optional callback to run once all the
+ * functions have completed. This function gets a results array (or object)
+ * containing all the result arguments passed to the `task` callbacks. Invoked
+ * with (err, result).
+ * @return {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * //Using Callbacks
+ * async.series([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             // do some async task
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             // then do another async task
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ], function(err, results) {
+ *     console.log(results);
+ *     // results is equal to ['one','two']
+ * });
+ *
+ * // an example using objects instead of arrays
+ * async.series({
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             // do some async task
+ *             callback(null, 1);
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         setTimeout(function() {
+ *             // then do another async task
+ *             callback(null, 2);
+ *         }, 100);
+ *     }
+ * }, function(err, results) {
+ *     console.log(results);
+ *     // results is equal to: { one: 1, two: 2 }
+ * });
+ *
+ * //Using Promises
+ * async.series([
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'one');
+ *         }, 200);
+ *     },
+ *     function(callback) {
+ *         setTimeout(function() {
+ *             callback(null, 'two');
+ *         }, 100);
+ *     }
+ * ]).then(results => {
+ *     console.log(results);
+ *     // results is equal to ['one','two']
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // an example using an object instead of an array
+ * async.series({
+ *     one: function(callback) {
+ *         setTimeout(function() {
+ *             // do some async task
+ *             callback(null, 1);
+ *         }, 200);
+ *     },
+ *     two: function(callback) {
+ *         setTimeout(function() {
+ *             // then do another async task
+ *             callback(null, 2);
+ *         }, 100);
+ *     }
+ * }).then(results => {
+ *     console.log(results);
+ *     // results is equal to: { one: 1, two: 2 }
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * //Using async/await
+ * async () => {
+ *     try {
+ *         let results = await async.series([
+ *             function(callback) {
+ *                 setTimeout(function() {
+ *                     // do some async task
+ *                     callback(null, 'one');
+ *                 }, 200);
+ *             },
+ *             function(callback) {
+ *                 setTimeout(function() {
+ *                     // then do another async task
+ *                     callback(null, 'two');
+ *                 }, 100);
+ *             }
+ *         ]);
+ *         console.log(results);
+ *         // results is equal to ['one','two']
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * // an example using an object instead of an array
+ * async () => {
+ *     try {
+ *         let results = await async.parallel({
+ *             one: function(callback) {
+ *                 setTimeout(function() {
+ *                     // do some async task
+ *                     callback(null, 1);
+ *                 }, 200);
+ *             },
+ *            two: function(callback) {
+ *                 setTimeout(function() {
+ *                     // then do another async task
+ *                     callback(null, 2);
+ *                 }, 100);
+ *            }
+ *         });
+ *         console.log(results);
+ *         // results is equal to: { one: 1, two: 2 }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function series(tasks, callback) {
+  return (0, _parallel3.default)(_eachOfSeries2.default, tasks, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/setImmediate.js b/node_modules/async/setImmediate.js
new file mode 100644
index 0000000000000000000000000000000000000000..c712ec3b49b25c72bbe30931c386b5eaa10d8014
--- /dev/null
+++ b/node_modules/async/setImmediate.js
@@ -0,0 +1,45 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _setImmediate = require('./internal/setImmediate.js');
+
+var _setImmediate2 = _interopRequireDefault(_setImmediate);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Calls `callback` on a later loop around the event loop. In Node.js this just
+ * calls `setImmediate`.  In the browser it will use `setImmediate` if
+ * available, otherwise `setTimeout(callback, 0)`, which means other higher
+ * priority events may precede the execution of `callback`.
+ *
+ * This is used internally for browser-compatibility purposes.
+ *
+ * @name setImmediate
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @see [async.nextTick]{@link module:Utils.nextTick}
+ * @category Util
+ * @param {Function} callback - The function to call on a later loop around
+ * the event loop. Invoked with (args...).
+ * @param {...*} args... - any number of additional arguments to pass to the
+ * callback on the next tick.
+ * @example
+ *
+ * var call_order = [];
+ * async.nextTick(function() {
+ *     call_order.push('two');
+ *     // call_order now equals ['one','two']
+ * });
+ * call_order.push('one');
+ *
+ * async.setImmediate(function (a, b, c) {
+ *     // a, b, and c equal 1, 2, and 3
+ * }, 1, 2, 3);
+ */
+exports.default = _setImmediate2.default;
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/some.js b/node_modules/async/some.js
new file mode 100644
index 0000000000000000000000000000000000000000..2046cf640252a7898e9eba24d1b8a50130ff72a6
--- /dev/null
+++ b/node_modules/async/some.js
@@ -0,0 +1,122 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Returns `true` if at least one element in the `coll` satisfies an async test.
+ * If any iteratee call returns `true`, the main `callback` is immediately
+ * called.
+ *
+ * @name some
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @alias any
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collections in parallel.
+ * The iteratee should complete with a boolean `result` value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the iteratee functions have finished.
+ * Result will be either `true` or `false` depending on the values of the async
+ * tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // dir1 is a directory that contains file1.txt, file2.txt
+ * // dir2 is a directory that contains file3.txt, file4.txt
+ * // dir3 is a directory that contains file5.txt
+ * // dir4 does not exist
+ *
+ * // asynchronous function that checks if a file exists
+ * function fileExists(file, callback) {
+ *    fs.access(file, fs.constants.F_OK, (err) => {
+ *        callback(null, !err);
+ *    });
+ * }
+ *
+ * // Using callbacks
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists,
+ *    function(err, result) {
+ *        console.log(result);
+ *        // true
+ *        // result is true since some file in the list exists
+ *    }
+ *);
+ *
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists,
+ *    function(err, result) {
+ *        console.log(result);
+ *        // false
+ *        // result is false since none of the files exists
+ *    }
+ *);
+ *
+ * // Using Promises
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // true
+ *     // result is true since some file in the list exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists)
+ * .then( result => {
+ *     console.log(result);
+ *     // false
+ *     // result is false since none of the files exists
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir3/file5.txt'], fileExists);
+ *         console.log(result);
+ *         // true
+ *         // result is true since some file in the list exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ * async () => {
+ *     try {
+ *         let result = await async.some(['dir1/missing.txt','dir2/missing.txt','dir4/missing.txt'], fileExists);
+ *         console.log(result);
+ *         // false
+ *         // result is false since none of the files exists
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function some(coll, iteratee, callback) {
+  return (0, _createTester2.default)(Boolean, res => res)(_eachOf2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(some, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/someLimit.js b/node_modules/async/someLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..c8a295a8b4f760d468be496af58b4b6d126219ec
--- /dev/null
+++ b/node_modules/async/someLimit.js
@@ -0,0 +1,47 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfLimit = require('./internal/eachOfLimit.js');
+
+var _eachOfLimit2 = _interopRequireDefault(_eachOfLimit);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`some`]{@link module:Collections.some} but runs a maximum of `limit` async operations at a time.
+ *
+ * @name someLimit
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.some]{@link module:Collections.some}
+ * @alias anyLimit
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collections in parallel.
+ * The iteratee should complete with a boolean `result` value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the iteratee functions have finished.
+ * Result will be either `true` or `false` depending on the values of the async
+ * tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function someLimit(coll, limit, iteratee, callback) {
+  return (0, _createTester2.default)(Boolean, res => res)((0, _eachOfLimit2.default)(limit), coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(someLimit, 4);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/someSeries.js b/node_modules/async/someSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..ee0654ba69fafcecbc398624e6b71b2b109268a8
--- /dev/null
+++ b/node_modules/async/someSeries.js
@@ -0,0 +1,46 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createTester = require('./internal/createTester.js');
+
+var _createTester2 = _interopRequireDefault(_createTester);
+
+var _eachOfSeries = require('./eachOfSeries.js');
+
+var _eachOfSeries2 = _interopRequireDefault(_eachOfSeries);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [`some`]{@link module:Collections.some} but runs only a single async operation at a time.
+ *
+ * @name someSeries
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @see [async.some]{@link module:Collections.some}
+ * @alias anySeries
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async truth test to apply to each item
+ * in the collections in series.
+ * The iteratee should complete with a boolean `result` value.
+ * Invoked with (item, callback).
+ * @param {Function} [callback] - A callback which is called as soon as any
+ * iteratee returns `true`, or after all the iteratee functions have finished.
+ * Result will be either `true` or `false` depending on the values of the async
+ * tests. Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ */
+function someSeries(coll, iteratee, callback) {
+  return (0, _createTester2.default)(Boolean, res => res)(_eachOfSeries2.default, coll, iteratee, callback);
+}
+exports.default = (0, _awaitify2.default)(someSeries, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/sortBy.js b/node_modules/async/sortBy.js
new file mode 100644
index 0000000000000000000000000000000000000000..d17fb6a286645f4f5ba8249cd06155ac313a13ce
--- /dev/null
+++ b/node_modules/async/sortBy.js
@@ -0,0 +1,190 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _map = require('./map.js');
+
+var _map2 = _interopRequireDefault(_map);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Sorts a list by the results of running each `coll` value through an async
+ * `iteratee`.
+ *
+ * @name sortBy
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {AsyncFunction} iteratee - An async function to apply to each item in
+ * `coll`.
+ * The iteratee should complete with a value to use as the sort criteria as
+ * its `result`.
+ * Invoked with (item, callback).
+ * @param {Function} callback - A callback which is called after all the
+ * `iteratee` functions have finished, or an error occurs. Results is the items
+ * from the original `coll` sorted by the values returned by the `iteratee`
+ * calls. Invoked with (err, results).
+ * @returns {Promise} a promise, if no callback passed
+ * @example
+ *
+ * // bigfile.txt is a file that is 251100 bytes in size
+ * // mediumfile.txt is a file that is 11000 bytes in size
+ * // smallfile.txt is a file that is 121 bytes in size
+ *
+ * // asynchronous function that returns the file size in bytes
+ * function getFileSizeInBytes(file, callback) {
+ *     fs.stat(file, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         callback(null, stat.size);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes,
+ *     function(err, results) {
+ *         if (err) {
+ *             console.log(err);
+ *         } else {
+ *             console.log(results);
+ *             // results is now the original array of files sorted by
+ *             // file size (ascending by default), e.g.
+ *             // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+ *         }
+ *     }
+ * );
+ *
+ * // By modifying the callback parameter the
+ * // sorting order can be influenced:
+ *
+ * // ascending order
+ * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], function(file, callback) {
+ *     getFileSizeInBytes(file, function(getFileSizeErr, fileSize) {
+ *         if (getFileSizeErr) return callback(getFileSizeErr);
+ *         callback(null, fileSize);
+ *     });
+ * }, function(err, results) {
+ *         if (err) {
+ *             console.log(err);
+ *         } else {
+ *             console.log(results);
+ *             // results is now the original array of files sorted by
+ *             // file size (ascending by default), e.g.
+ *             // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+ *         }
+ *     }
+ * );
+ *
+ * // descending order
+ * async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], function(file, callback) {
+ *     getFileSizeInBytes(file, function(getFileSizeErr, fileSize) {
+ *         if (getFileSizeErr) {
+ *             return callback(getFileSizeErr);
+ *         }
+ *         callback(null, fileSize * -1);
+ *     });
+ * }, function(err, results) {
+ *         if (err) {
+ *             console.log(err);
+ *         } else {
+ *             console.log(results);
+ *             // results is now the original array of files sorted by
+ *             // file size (ascending by default), e.g.
+ *             // [ 'bigfile.txt', 'mediumfile.txt', 'smallfile.txt']
+ *         }
+ *     }
+ * );
+ *
+ * // Error handling
+ * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes,
+ *     function(err, results) {
+ *         if (err) {
+ *             console.log(err);
+ *             // [ Error: ENOENT: no such file or directory ]
+ *         } else {
+ *             console.log(results);
+ *         }
+ *     }
+ * );
+ *
+ * // Using Promises
+ * async.sortBy(['mediumfile.txt','smallfile.txt','bigfile.txt'], getFileSizeInBytes)
+ * .then( results => {
+ *     console.log(results);
+ *     // results is now the original array of files sorted by
+ *     // file size (ascending by default), e.g.
+ *     // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+ * }).catch( err => {
+ *     console.log(err);
+ * });
+ *
+ * // Error handling
+ * async.sortBy(['mediumfile.txt','smallfile.txt','missingfile.txt'], getFileSizeInBytes)
+ * .then( results => {
+ *     console.log(results);
+ * }).catch( err => {
+ *     console.log(err);
+ *     // [ Error: ENOENT: no such file or directory ]
+ * });
+ *
+ * // Using async/await
+ * (async () => {
+ *     try {
+ *         let results = await async.sortBy(['bigfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes);
+ *         console.log(results);
+ *         // results is now the original array of files sorted by
+ *         // file size (ascending by default), e.g.
+ *         // [ 'smallfile.txt', 'mediumfile.txt', 'bigfile.txt']
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * })();
+ *
+ * // Error handling
+ * async () => {
+ *     try {
+ *         let results = await async.sortBy(['missingfile.txt','mediumfile.txt','smallfile.txt'], getFileSizeInBytes);
+ *         console.log(results);
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *         // [ Error: ENOENT: no such file or directory ]
+ *     }
+ * }
+ *
+ */
+function sortBy(coll, iteratee, callback) {
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+    return (0, _map2.default)(coll, (x, iterCb) => {
+        _iteratee(x, (err, criteria) => {
+            if (err) return iterCb(err);
+            iterCb(err, { value: x, criteria });
+        });
+    }, (err, results) => {
+        if (err) return callback(err);
+        callback(null, results.sort(comparator).map(v => v.value));
+    });
+
+    function comparator(left, right) {
+        var a = left.criteria,
+            b = right.criteria;
+        return a < b ? -1 : a > b ? 1 : 0;
+    }
+}
+exports.default = (0, _awaitify2.default)(sortBy, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/support/sync-package-managers.js b/node_modules/async/support/sync-package-managers.js
deleted file mode 100644
index 30cb7c2d0cfc5f905781f16a681a9c3fcfa8b642..0000000000000000000000000000000000000000
--- a/node_modules/async/support/sync-package-managers.js
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env node
-
-// This should probably be its own module but complaints about bower/etc.
-// support keep coming up and I'd rather just enable the workflow here for now
-// and figure out where this should live later. -- @beaugunderson
-
-var fs = require('fs');
-var _ = require('lodash');
-
-var packageJson = require('../package.json');
-
-var IGNORES = ['**/.*', 'node_modules', 'bower_components', 'test', 'tests'];
-var INCLUDES = ['lib/async.js', 'README.md', 'LICENSE'];
-var REPOSITORY_NAME = 'caolan/async';
-
-packageJson.jam = {
-  main: packageJson.main,
-  include: INCLUDES,
-  categories: ['Utilities']
-};
-
-packageJson.spm = {
-  main: packageJson.main
-};
-
-packageJson.volo = {
-  main: packageJson.main,
-  ignore: IGNORES
-};
-
-var bowerSpecific = {
-  moduleType: ['amd', 'globals', 'node'],
-  ignore: IGNORES,
-  authors: [packageJson.author]
-};
-
-var bowerInclude = ['name', 'description', 'version', 'main', 'keywords',
-  'license', 'homepage', 'repository', 'devDependencies'];
-
-var componentSpecific = {
-  repository: REPOSITORY_NAME,
-  scripts: [packageJson.main]
-};
-
-var componentInclude = ['name', 'description', 'version', 'keywords',
-  'license'];
-
-var bowerJson = _.merge({}, _.pick(packageJson, bowerInclude), bowerSpecific);
-var componentJson = _.merge({}, _.pick(packageJson, componentInclude), componentSpecific);
-
-fs.writeFileSync('./bower.json', JSON.stringify(bowerJson, null, 2));
-fs.writeFileSync('./component.json', JSON.stringify(componentJson, null, 2));
-fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, 2));
diff --git a/node_modules/async/timeout.js b/node_modules/async/timeout.js
new file mode 100644
index 0000000000000000000000000000000000000000..dd58eb38d9ff55c2fd00617cf9e1d376209673b7
--- /dev/null
+++ b/node_modules/async/timeout.js
@@ -0,0 +1,89 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = timeout;
+
+var _initialParams = require('./internal/initialParams.js');
+
+var _initialParams2 = _interopRequireDefault(_initialParams);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Sets a time limit on an asynchronous function. If the function does not call
+ * its callback within the specified milliseconds, it will be called with a
+ * timeout error. The code property for the error object will be `'ETIMEDOUT'`.
+ *
+ * @name timeout
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @category Util
+ * @param {AsyncFunction} asyncFn - The async function to limit in time.
+ * @param {number} milliseconds - The specified time limit.
+ * @param {*} [info] - Any variable you want attached (`string`, `object`, etc)
+ * to timeout Error for more information..
+ * @returns {AsyncFunction} Returns a wrapped function that can be used with any
+ * of the control flow functions.
+ * Invoke this function with the same parameters as you would `asyncFunc`.
+ * @example
+ *
+ * function myFunction(foo, callback) {
+ *     doAsyncTask(foo, function(err, data) {
+ *         // handle errors
+ *         if (err) return callback(err);
+ *
+ *         // do some stuff ...
+ *
+ *         // return processed data
+ *         return callback(null, data);
+ *     });
+ * }
+ *
+ * var wrapped = async.timeout(myFunction, 1000);
+ *
+ * // call `wrapped` as you would `myFunction`
+ * wrapped({ bar: 'bar' }, function(err, data) {
+ *     // if `myFunction` takes < 1000 ms to execute, `err`
+ *     // and `data` will have their expected values
+ *
+ *     // else `err` will be an Error with the code 'ETIMEDOUT'
+ * });
+ */
+function timeout(asyncFn, milliseconds, info) {
+    var fn = (0, _wrapAsync2.default)(asyncFn);
+
+    return (0, _initialParams2.default)((args, callback) => {
+        var timedOut = false;
+        var timer;
+
+        function timeoutCallback() {
+            var name = asyncFn.name || 'anonymous';
+            var error = new Error('Callback function "' + name + '" timed out.');
+            error.code = 'ETIMEDOUT';
+            if (info) {
+                error.info = info;
+            }
+            timedOut = true;
+            callback(error);
+        }
+
+        args.push((...cbArgs) => {
+            if (!timedOut) {
+                callback(...cbArgs);
+                clearTimeout(timer);
+            }
+        });
+
+        // setup timer and call original function
+        timer = setTimeout(timeoutCallback, milliseconds);
+        fn(...args);
+    });
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/times.js b/node_modules/async/times.js
new file mode 100644
index 0000000000000000000000000000000000000000..4484c73e6b1583016afb1bfc9bbd68d521071e65
--- /dev/null
+++ b/node_modules/async/times.js
@@ -0,0 +1,50 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = times;
+
+var _timesLimit = require('./timesLimit.js');
+
+var _timesLimit2 = _interopRequireDefault(_timesLimit);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Calls the `iteratee` function `n` times, and accumulates results in the same
+ * manner you would use with [map]{@link module:Collections.map}.
+ *
+ * @name times
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.map]{@link module:Collections.map}
+ * @category Control Flow
+ * @param {number} n - The number of times to run the function.
+ * @param {AsyncFunction} iteratee - The async function to call `n` times.
+ * Invoked with the iteration index and a callback: (n, next).
+ * @param {Function} callback - see {@link module:Collections.map}.
+ * @returns {Promise} a promise, if no callback is provided
+ * @example
+ *
+ * // Pretend this is some complicated async factory
+ * var createUser = function(id, callback) {
+ *     callback(null, {
+ *         id: 'user' + id
+ *     });
+ * };
+ *
+ * // generate 5 users
+ * async.times(5, function(n, next) {
+ *     createUser(n, function(err, user) {
+ *         next(err, user);
+ *     });
+ * }, function(err, users) {
+ *     // we should now have 5 users
+ * });
+ */
+function times(n, iteratee, callback) {
+  return (0, _timesLimit2.default)(n, Infinity, iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/timesLimit.js b/node_modules/async/timesLimit.js
new file mode 100644
index 0000000000000000000000000000000000000000..9fb0ba35fcbf7aba3e5c5ce91216f33c5e2afa99
--- /dev/null
+++ b/node_modules/async/timesLimit.js
@@ -0,0 +1,43 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = timesLimit;
+
+var _mapLimit = require('./mapLimit.js');
+
+var _mapLimit2 = _interopRequireDefault(_mapLimit);
+
+var _range = require('./internal/range.js');
+
+var _range2 = _interopRequireDefault(_range);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [times]{@link module:ControlFlow.times} but runs a maximum of `limit` async operations at a
+ * time.
+ *
+ * @name timesLimit
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.times]{@link module:ControlFlow.times}
+ * @category Control Flow
+ * @param {number} count - The number of times to run the function.
+ * @param {number} limit - The maximum number of async operations at a time.
+ * @param {AsyncFunction} iteratee - The async function to call `n` times.
+ * Invoked with the iteration index and a callback: (n, next).
+ * @param {Function} callback - see [async.map]{@link module:Collections.map}.
+ * @returns {Promise} a promise, if no callback is provided
+ */
+function timesLimit(count, limit, iteratee, callback) {
+  var _iteratee = (0, _wrapAsync2.default)(iteratee);
+  return (0, _mapLimit2.default)((0, _range2.default)(count), limit, _iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/timesSeries.js b/node_modules/async/timesSeries.js
new file mode 100644
index 0000000000000000000000000000000000000000..a10f0cbea748d83d3d684feb9431330a15de3118
--- /dev/null
+++ b/node_modules/async/timesSeries.js
@@ -0,0 +1,32 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = timesSeries;
+
+var _timesLimit = require('./timesLimit.js');
+
+var _timesLimit2 = _interopRequireDefault(_timesLimit);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * The same as [times]{@link module:ControlFlow.times} but runs only a single async operation at a time.
+ *
+ * @name timesSeries
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.times]{@link module:ControlFlow.times}
+ * @category Control Flow
+ * @param {number} n - The number of times to run the function.
+ * @param {AsyncFunction} iteratee - The async function to call `n` times.
+ * Invoked with the iteration index and a callback: (n, next).
+ * @param {Function} callback - see {@link module:Collections.map}.
+ * @returns {Promise} a promise, if no callback is provided
+ */
+function timesSeries(n, iteratee, callback) {
+  return (0, _timesLimit2.default)(n, 1, iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/transform.js b/node_modules/async/transform.js
new file mode 100644
index 0000000000000000000000000000000000000000..75b754e9faa1aa041a41a98503a31ed925a85c76
--- /dev/null
+++ b/node_modules/async/transform.js
@@ -0,0 +1,173 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = transform;
+
+var _eachOf = require('./eachOf.js');
+
+var _eachOf2 = _interopRequireDefault(_eachOf);
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _promiseCallback = require('./internal/promiseCallback.js');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * A relative of `reduce`.  Takes an Object or Array, and iterates over each
+ * element in parallel, each step potentially mutating an `accumulator` value.
+ * The type of the accumulator defaults to the type of collection passed in.
+ *
+ * @name transform
+ * @static
+ * @memberOf module:Collections
+ * @method
+ * @category Collection
+ * @param {Array|Iterable|AsyncIterable|Object} coll - A collection to iterate over.
+ * @param {*} [accumulator] - The initial state of the transform.  If omitted,
+ * it will default to an empty Object or Array, depending on the type of `coll`
+ * @param {AsyncFunction} iteratee - A function applied to each item in the
+ * collection that potentially modifies the accumulator.
+ * Invoked with (accumulator, item, key, callback).
+ * @param {Function} [callback] - A callback which is called after all the
+ * `iteratee` functions have finished. Result is the transformed accumulator.
+ * Invoked with (err, result).
+ * @returns {Promise} a promise, if no callback provided
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ *
+ * // helper function that returns human-readable size format from bytes
+ * function formatBytes(bytes, decimals = 2) {
+ *   // implementation not included for brevity
+ *   return humanReadbleFilesize;
+ * }
+ *
+ * const fileList = ['file1.txt','file2.txt','file3.txt'];
+ *
+ * // asynchronous function that returns the file size, transformed to human-readable format
+ * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc.
+ * function transformFileSize(acc, value, key, callback) {
+ *     fs.stat(value, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         acc[key] = formatBytes(stat.size);
+ *         callback(null);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.transform(fileList, transformFileSize, function(err, result) {
+ *     if(err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.transform(fileList, transformFileSize)
+ * .then(result => {
+ *     console.log(result);
+ *     // [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * (async () => {
+ *     try {
+ *         let result = await async.transform(fileList, transformFileSize);
+ *         console.log(result);
+ *         // [ '1000 Bytes', '1.95 KB', '2.93 KB' ]
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * })();
+ *
+ * @example
+ *
+ * // file1.txt is a file that is 1000 bytes in size
+ * // file2.txt is a file that is 2000 bytes in size
+ * // file3.txt is a file that is 3000 bytes in size
+ *
+ * // helper function that returns human-readable size format from bytes
+ * function formatBytes(bytes, decimals = 2) {
+ *   // implementation not included for brevity
+ *   return humanReadbleFilesize;
+ * }
+ *
+ * const fileMap = { f1: 'file1.txt', f2: 'file2.txt', f3: 'file3.txt' };
+ *
+ * // asynchronous function that returns the file size, transformed to human-readable format
+ * // e.g. 1024 bytes = 1KB, 1234 bytes = 1.21 KB, 1048576 bytes = 1MB, etc.
+ * function transformFileSize(acc, value, key, callback) {
+ *     fs.stat(value, function(err, stat) {
+ *         if (err) {
+ *             return callback(err);
+ *         }
+ *         acc[key] = formatBytes(stat.size);
+ *         callback(null);
+ *     });
+ * }
+ *
+ * // Using callbacks
+ * async.transform(fileMap, transformFileSize, function(err, result) {
+ *     if(err) {
+ *         console.log(err);
+ *     } else {
+ *         console.log(result);
+ *         // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
+ *     }
+ * });
+ *
+ * // Using Promises
+ * async.transform(fileMap, transformFileSize)
+ * .then(result => {
+ *     console.log(result);
+ *     // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
+ * }).catch(err => {
+ *     console.log(err);
+ * });
+ *
+ * // Using async/await
+ * async () => {
+ *     try {
+ *         let result = await async.transform(fileMap, transformFileSize);
+ *         console.log(result);
+ *         // { f1: '1000 Bytes', f2: '1.95 KB', f3: '2.93 KB' }
+ *     }
+ *     catch (err) {
+ *         console.log(err);
+ *     }
+ * }
+ *
+ */
+function transform(coll, accumulator, iteratee, callback) {
+    if (arguments.length <= 3 && typeof accumulator === 'function') {
+        callback = iteratee;
+        iteratee = accumulator;
+        accumulator = Array.isArray(coll) ? [] : {};
+    }
+    callback = (0, _once2.default)(callback || (0, _promiseCallback.promiseCallback)());
+    var _iteratee = (0, _wrapAsync2.default)(iteratee);
+
+    (0, _eachOf2.default)(coll, (v, k, cb) => {
+        _iteratee(accumulator, v, k, cb);
+    }, err => callback(err, accumulator));
+    return callback[_promiseCallback.PROMISE_SYMBOL];
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/tryEach.js b/node_modules/async/tryEach.js
new file mode 100644
index 0000000000000000000000000000000000000000..82fe8ec195f7284f4a570c60a92a61d3783e5762
--- /dev/null
+++ b/node_modules/async/tryEach.js
@@ -0,0 +1,78 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _eachSeries = require('./eachSeries.js');
+
+var _eachSeries2 = _interopRequireDefault(_eachSeries);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * It runs each task in series but stops whenever any of the functions were
+ * successful. If one of the tasks were successful, the `callback` will be
+ * passed the result of the successful task. If all tasks fail, the callback
+ * will be passed the error and result (if any) of the final attempt.
+ *
+ * @name tryEach
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array|Iterable|AsyncIterable|Object} tasks - A collection containing functions to
+ * run, each function is passed a `callback(err, result)` it must call on
+ * completion with an error `err` (which can be `null`) and an optional `result`
+ * value.
+ * @param {Function} [callback] - An optional callback which is called when one
+ * of the tasks has succeeded, or all have failed. It receives the `err` and
+ * `result` arguments of the last attempt at completing the `task`. Invoked with
+ * (err, results).
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ * async.tryEach([
+ *     function getDataFromFirstWebsite(callback) {
+ *         // Try getting the data from the first website
+ *         callback(err, data);
+ *     },
+ *     function getDataFromSecondWebsite(callback) {
+ *         // First website failed,
+ *         // Try getting the data from the backup website
+ *         callback(err, data);
+ *     }
+ * ],
+ * // optional callback
+ * function(err, results) {
+ *     Now do something with the data.
+ * });
+ *
+ */
+function tryEach(tasks, callback) {
+    var error = null;
+    var result;
+    return (0, _eachSeries2.default)(tasks, (task, taskCb) => {
+        (0, _wrapAsync2.default)(task)((err, ...args) => {
+            if (err === false) return taskCb(err);
+
+            if (args.length < 2) {
+                [result] = args;
+            } else {
+                result = args;
+            }
+            error = err;
+            taskCb(err ? null : {});
+        });
+    }, () => callback(error, result));
+}
+
+exports.default = (0, _awaitify2.default)(tryEach);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/unmemoize.js b/node_modules/async/unmemoize.js
new file mode 100644
index 0000000000000000000000000000000000000000..47a92b42121f07fbe36dd1bdfa77b79065bcdceb
--- /dev/null
+++ b/node_modules/async/unmemoize.js
@@ -0,0 +1,25 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = unmemoize;
+/**
+ * Undoes a [memoize]{@link module:Utils.memoize}d function, reverting it to the original,
+ * unmemoized form. Handy for testing.
+ *
+ * @name unmemoize
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @see [async.memoize]{@link module:Utils.memoize}
+ * @category Util
+ * @param {AsyncFunction} fn - the memoized function
+ * @returns {AsyncFunction} a function that calls the original unmemoized function
+ */
+function unmemoize(fn) {
+    return (...args) => {
+        return (fn.unmemoized || fn)(...args);
+    };
+}
+module.exports = exports["default"];
\ No newline at end of file
diff --git a/node_modules/async/until.js b/node_modules/async/until.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c71e51449b5386c621792b0dae6530c0c8dbe96
--- /dev/null
+++ b/node_modules/async/until.js
@@ -0,0 +1,61 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.default = until;
+
+var _whilst = require('./whilst.js');
+
+var _whilst2 = _interopRequireDefault(_whilst);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Repeatedly call `iteratee` until `test` returns `true`. Calls `callback` when
+ * stopped, or an error occurs. `callback` will be passed an error and any
+ * arguments passed to the final `iteratee`'s callback.
+ *
+ * The inverse of [whilst]{@link module:ControlFlow.whilst}.
+ *
+ * @name until
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @see [async.whilst]{@link module:ControlFlow.whilst}
+ * @category Control Flow
+ * @param {AsyncFunction} test - asynchronous truth test to perform before each
+ * execution of `iteratee`. Invoked with (callback).
+ * @param {AsyncFunction} iteratee - An async function which is called each time
+ * `test` fails. Invoked with (callback).
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has passed and repeated execution of `iteratee` has stopped. `callback`
+ * will be passed an error and any arguments passed to the final `iteratee`'s
+ * callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if a callback is not passed
+ *
+ * @example
+ * const results = []
+ * let finished = false
+ * async.until(function test(cb) {
+ *     cb(null, finished)
+ * }, function iter(next) {
+ *     fetchPage(url, (err, body) => {
+ *         if (err) return next(err)
+ *         results = results.concat(body.objects)
+ *         finished = !!body.next
+ *         next(err)
+ *     })
+ * }, function done (err) {
+ *     // all pages have been fetched
+ * })
+ */
+function until(test, iteratee, callback) {
+  const _test = (0, _wrapAsync2.default)(test);
+  return (0, _whilst2.default)(cb => _test((err, truth) => cb(err, !truth)), iteratee, callback);
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/waterfall.js b/node_modules/async/waterfall.js
new file mode 100644
index 0000000000000000000000000000000000000000..fcd0dc1c8e54e29da8206535169c79da45d16aa1
--- /dev/null
+++ b/node_modules/async/waterfall.js
@@ -0,0 +1,105 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _once = require('./internal/once.js');
+
+var _once2 = _interopRequireDefault(_once);
+
+var _onlyOnce = require('./internal/onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Runs the `tasks` array of functions in series, each passing their results to
+ * the next in the array. However, if any of the `tasks` pass an error to their
+ * own callback, the next function is not executed, and the main `callback` is
+ * immediately called with the error.
+ *
+ * @name waterfall
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {Array} tasks - An array of [async functions]{@link AsyncFunction}
+ * to run.
+ * Each function should complete with any number of `result` values.
+ * The `result` values will be passed as arguments, in order, to the next task.
+ * @param {Function} [callback] - An optional callback to run once all the
+ * functions have completed. This will be passed the results of the last task's
+ * callback. Invoked with (err, [results]).
+ * @returns {Promise} a promise, if a callback is omitted
+ * @example
+ *
+ * async.waterfall([
+ *     function(callback) {
+ *         callback(null, 'one', 'two');
+ *     },
+ *     function(arg1, arg2, callback) {
+ *         // arg1 now equals 'one' and arg2 now equals 'two'
+ *         callback(null, 'three');
+ *     },
+ *     function(arg1, callback) {
+ *         // arg1 now equals 'three'
+ *         callback(null, 'done');
+ *     }
+ * ], function (err, result) {
+ *     // result now equals 'done'
+ * });
+ *
+ * // Or, with named functions:
+ * async.waterfall([
+ *     myFirstFunction,
+ *     mySecondFunction,
+ *     myLastFunction,
+ * ], function (err, result) {
+ *     // result now equals 'done'
+ * });
+ * function myFirstFunction(callback) {
+ *     callback(null, 'one', 'two');
+ * }
+ * function mySecondFunction(arg1, arg2, callback) {
+ *     // arg1 now equals 'one' and arg2 now equals 'two'
+ *     callback(null, 'three');
+ * }
+ * function myLastFunction(arg1, callback) {
+ *     // arg1 now equals 'three'
+ *     callback(null, 'done');
+ * }
+ */
+function waterfall(tasks, callback) {
+    callback = (0, _once2.default)(callback);
+    if (!Array.isArray(tasks)) return callback(new Error('First argument to waterfall must be an array of functions'));
+    if (!tasks.length) return callback();
+    var taskIndex = 0;
+
+    function nextTask(args) {
+        var task = (0, _wrapAsync2.default)(tasks[taskIndex++]);
+        task(...args, (0, _onlyOnce2.default)(next));
+    }
+
+    function next(err, ...args) {
+        if (err === false) return;
+        if (err || taskIndex === tasks.length) {
+            return callback(err, ...args);
+        }
+        nextTask(args);
+    }
+
+    nextTask([]);
+}
+
+exports.default = (0, _awaitify2.default)(waterfall);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/whilst.js b/node_modules/async/whilst.js
new file mode 100644
index 0000000000000000000000000000000000000000..32a47762a518d98e844dcdbda9d1f92aa1106b75
--- /dev/null
+++ b/node_modules/async/whilst.js
@@ -0,0 +1,78 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+
+var _onlyOnce = require('./internal/onlyOnce.js');
+
+var _onlyOnce2 = _interopRequireDefault(_onlyOnce);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+var _wrapAsync2 = _interopRequireDefault(_wrapAsync);
+
+var _awaitify = require('./internal/awaitify.js');
+
+var _awaitify2 = _interopRequireDefault(_awaitify);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Repeatedly call `iteratee`, while `test` returns `true`. Calls `callback` when
+ * stopped, or an error occurs.
+ *
+ * @name whilst
+ * @static
+ * @memberOf module:ControlFlow
+ * @method
+ * @category Control Flow
+ * @param {AsyncFunction} test - asynchronous truth test to perform before each
+ * execution of `iteratee`. Invoked with ().
+ * @param {AsyncFunction} iteratee - An async function which is called each time
+ * `test` passes. Invoked with (callback).
+ * @param {Function} [callback] - A callback which is called after the test
+ * function has failed and repeated execution of `iteratee` has stopped. `callback`
+ * will be passed an error and any arguments passed to the final `iteratee`'s
+ * callback. Invoked with (err, [results]);
+ * @returns {Promise} a promise, if no callback is passed
+ * @example
+ *
+ * var count = 0;
+ * async.whilst(
+ *     function test(cb) { cb(null, count < 5); },
+ *     function iter(callback) {
+ *         count++;
+ *         setTimeout(function() {
+ *             callback(null, count);
+ *         }, 1000);
+ *     },
+ *     function (err, n) {
+ *         // 5 seconds have passed, n = 5
+ *     }
+ * );
+ */
+function whilst(test, iteratee, callback) {
+    callback = (0, _onlyOnce2.default)(callback);
+    var _fn = (0, _wrapAsync2.default)(iteratee);
+    var _test = (0, _wrapAsync2.default)(test);
+    var results = [];
+
+    function next(err, ...rest) {
+        if (err) return callback(err);
+        results = rest;
+        if (err === false) return;
+        _test(check);
+    }
+
+    function check(err, truth) {
+        if (err) return callback(err);
+        if (err === false) return;
+        if (!truth) return callback(null, ...results);
+        _fn(next);
+    }
+
+    return _test(check);
+}
+exports.default = (0, _awaitify2.default)(whilst, 3);
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/async/wrapSync.js b/node_modules/async/wrapSync.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c3bf886b2e6957e2b926af6cd9e83324960821c
--- /dev/null
+++ b/node_modules/async/wrapSync.js
@@ -0,0 +1,118 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+    value: true
+});
+exports.default = asyncify;
+
+var _initialParams = require('./internal/initialParams.js');
+
+var _initialParams2 = _interopRequireDefault(_initialParams);
+
+var _setImmediate = require('./internal/setImmediate.js');
+
+var _setImmediate2 = _interopRequireDefault(_setImmediate);
+
+var _wrapAsync = require('./internal/wrapAsync.js');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Take a sync function and make it async, passing its return value to a
+ * callback. This is useful for plugging sync functions into a waterfall,
+ * series, or other async functions. Any arguments passed to the generated
+ * function will be passed to the wrapped function (except for the final
+ * callback argument). Errors thrown will be passed to the callback.
+ *
+ * If the function passed to `asyncify` returns a Promise, that promises's
+ * resolved/rejected state will be used to call the callback, rather than simply
+ * the synchronous return value.
+ *
+ * This also means you can asyncify ES2017 `async` functions.
+ *
+ * @name asyncify
+ * @static
+ * @memberOf module:Utils
+ * @method
+ * @alias wrapSync
+ * @category Util
+ * @param {Function} func - The synchronous function, or Promise-returning
+ * function to convert to an {@link AsyncFunction}.
+ * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be
+ * invoked with `(args..., callback)`.
+ * @example
+ *
+ * // passing a regular synchronous function
+ * async.waterfall([
+ *     async.apply(fs.readFile, filename, "utf8"),
+ *     async.asyncify(JSON.parse),
+ *     function (data, next) {
+ *         // data is the result of parsing the text.
+ *         // If there was a parsing error, it would have been caught.
+ *     }
+ * ], callback);
+ *
+ * // passing a function returning a promise
+ * async.waterfall([
+ *     async.apply(fs.readFile, filename, "utf8"),
+ *     async.asyncify(function (contents) {
+ *         return db.model.create(contents);
+ *     }),
+ *     function (model, next) {
+ *         // `model` is the instantiated model object.
+ *         // If there was an error, this function would be skipped.
+ *     }
+ * ], callback);
+ *
+ * // es2017 example, though `asyncify` is not needed if your JS environment
+ * // supports async functions out of the box
+ * var q = async.queue(async.asyncify(async function(file) {
+ *     var intermediateStep = await processFile(file);
+ *     return await somePromise(intermediateStep)
+ * }));
+ *
+ * q.push(files);
+ */
+function asyncify(func) {
+    if ((0, _wrapAsync.isAsync)(func)) {
+        return function (...args /*, callback*/) {
+            const callback = args.pop();
+            const promise = func.apply(this, args);
+            return handlePromise(promise, callback);
+        };
+    }
+
+    return (0, _initialParams2.default)(function (args, callback) {
+        var result;
+        try {
+            result = func.apply(this, args);
+        } catch (e) {
+            return callback(e);
+        }
+        // if result is Promise object
+        if (result && typeof result.then === 'function') {
+            return handlePromise(result, callback);
+        } else {
+            callback(null, result);
+        }
+    });
+}
+
+function handlePromise(promise, callback) {
+    return promise.then(value => {
+        invokeCallback(callback, null, value);
+    }, err => {
+        invokeCallback(callback, err && err.message ? err : new Error(err));
+    });
+}
+
+function invokeCallback(callback, error, value) {
+    try {
+        callback(error, value);
+    } catch (err) {
+        (0, _setImmediate2.default)(e => {
+            throw e;
+        }, err);
+    }
+}
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/node_modules/buffer-from/LICENSE b/node_modules/buffer-from/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..e4bf1d69b1bb0df5acf1278e583264acdc1eefc5
--- /dev/null
+++ b/node_modules/buffer-from/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016, 2018 Linus Unnebäck
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/buffer-from/index.js b/node_modules/buffer-from/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..e1a58b5e8a06fd24ce5321aa6b08255dc9d0716d
--- /dev/null
+++ b/node_modules/buffer-from/index.js
@@ -0,0 +1,72 @@
+/* eslint-disable node/no-deprecated-api */
+
+var toString = Object.prototype.toString
+
+var isModern = (
+  typeof Buffer !== 'undefined' &&
+  typeof Buffer.alloc === 'function' &&
+  typeof Buffer.allocUnsafe === 'function' &&
+  typeof Buffer.from === 'function'
+)
+
+function isArrayBuffer (input) {
+  return toString.call(input).slice(8, -1) === 'ArrayBuffer'
+}
+
+function fromArrayBuffer (obj, byteOffset, length) {
+  byteOffset >>>= 0
+
+  var maxLength = obj.byteLength - byteOffset
+
+  if (maxLength < 0) {
+    throw new RangeError("'offset' is out of bounds")
+  }
+
+  if (length === undefined) {
+    length = maxLength
+  } else {
+    length >>>= 0
+
+    if (length > maxLength) {
+      throw new RangeError("'length' is out of bounds")
+    }
+  }
+
+  return isModern
+    ? Buffer.from(obj.slice(byteOffset, byteOffset + length))
+    : new Buffer(new Uint8Array(obj.slice(byteOffset, byteOffset + length)))
+}
+
+function fromString (string, encoding) {
+  if (typeof encoding !== 'string' || encoding === '') {
+    encoding = 'utf8'
+  }
+
+  if (!Buffer.isEncoding(encoding)) {
+    throw new TypeError('"encoding" must be a valid string encoding')
+  }
+
+  return isModern
+    ? Buffer.from(string, encoding)
+    : new Buffer(string, encoding)
+}
+
+function bufferFrom (value, encodingOrOffset, length) {
+  if (typeof value === 'number') {
+    throw new TypeError('"value" argument must not be a number')
+  }
+
+  if (isArrayBuffer(value)) {
+    return fromArrayBuffer(value, encodingOrOffset, length)
+  }
+
+  if (typeof value === 'string') {
+    return fromString(value, encodingOrOffset)
+  }
+
+  return isModern
+    ? Buffer.from(value)
+    : new Buffer(value)
+}
+
+module.exports = bufferFrom
diff --git a/node_modules/buffer-from/package.json b/node_modules/buffer-from/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..6ac5327bf8621ef03a3df8039518a98ba3d1648a
--- /dev/null
+++ b/node_modules/buffer-from/package.json
@@ -0,0 +1,19 @@
+{
+  "name": "buffer-from",
+  "version": "1.1.2",
+  "license": "MIT",
+  "repository": "LinusU/buffer-from",
+  "files": [
+    "index.js"
+  ],
+  "scripts": {
+    "test": "standard && node test"
+  },
+  "devDependencies": {
+    "standard": "^12.0.1"
+  },
+  "keywords": [
+    "buffer",
+    "buffer from"
+  ]
+}
diff --git a/node_modules/buffer-from/readme.md b/node_modules/buffer-from/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..9880a558a7c91fefb0e6908318fbd991b6b93dcf
--- /dev/null
+++ b/node_modules/buffer-from/readme.md
@@ -0,0 +1,69 @@
+# Buffer From
+
+A [ponyfill](https://ponyfill.com) for `Buffer.from`, uses native implementation if available.
+
+## Installation
+
+```sh
+npm install --save buffer-from
+```
+
+## Usage
+
+```js
+const bufferFrom = require('buffer-from')
+
+console.log(bufferFrom([1, 2, 3, 4]))
+//=> <Buffer 01 02 03 04>
+
+const arr = new Uint8Array([1, 2, 3, 4])
+console.log(bufferFrom(arr.buffer, 1, 2))
+//=> <Buffer 02 03>
+
+console.log(bufferFrom('test', 'utf8'))
+//=> <Buffer 74 65 73 74>
+
+const buf = bufferFrom('test')
+console.log(bufferFrom(buf))
+//=> <Buffer 74 65 73 74>
+```
+
+## API
+
+### bufferFrom(array)
+
+- `array` &lt;Array&gt;
+
+Allocates a new `Buffer` using an `array` of octets.
+
+### bufferFrom(arrayBuffer[, byteOffset[, length]])
+
+- `arrayBuffer` &lt;ArrayBuffer&gt; The `.buffer` property of a TypedArray or ArrayBuffer
+- `byteOffset` &lt;Integer&gt; Where to start copying from `arrayBuffer`. **Default:** `0`
+- `length` &lt;Integer&gt; How many bytes to copy from `arrayBuffer`. **Default:** `arrayBuffer.length - byteOffset`
+
+When passed a reference to the `.buffer` property of a TypedArray instance, the
+newly created `Buffer` will share the same allocated memory as the TypedArray.
+
+The optional `byteOffset` and `length` arguments specify a memory range within
+the `arrayBuffer` that will be shared by the `Buffer`.
+
+### bufferFrom(buffer)
+
+- `buffer` &lt;Buffer&gt; An existing `Buffer` to copy data from
+
+Copies the passed `buffer` data onto a new `Buffer` instance.
+
+### bufferFrom(string[, encoding])
+
+- `string` &lt;String&gt; A string to encode.
+- `encoding` &lt;String&gt; The encoding of `string`. **Default:** `'utf8'`
+
+Creates a new `Buffer` containing the given JavaScript string `string`. If
+provided, the `encoding` parameter identifies the character encoding of
+`string`.
+
+## See also
+
+- [buffer-alloc](https://github.com/LinusU/buffer-alloc) A ponyfill for `Buffer.alloc`
+- [buffer-alloc-unsafe](https://github.com/LinusU/buffer-alloc-unsafe) A ponyfill for `Buffer.allocUnsafe`
diff --git a/node_modules/busboy/.eslintrc.js b/node_modules/busboy/.eslintrc.js
new file mode 100644
index 0000000000000000000000000000000000000000..be9311d02655a22381f13078bfe868bcbd85b3a6
--- /dev/null
+++ b/node_modules/busboy/.eslintrc.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = {
+  extends: '@mscdex/eslint-config',
+};
diff --git a/node_modules/busboy/.github/workflows/ci.yml b/node_modules/busboy/.github/workflows/ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..799bae04adb62ae5b327afff21a37b8ab841ec2f
--- /dev/null
+++ b/node_modules/busboy/.github/workflows/ci.yml
@@ -0,0 +1,24 @@
+name: CI
+
+on:
+  pull_request:
+  push:
+    branches: [ master ]
+
+jobs:
+  tests-linux:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        node-version: [10.16.0, 10.x, 12.x, 14.x, 16.x]
+    steps:
+      - uses: actions/checkout@v2
+      - name: Use Node.js ${{ matrix.node-version }}
+        uses: actions/setup-node@v1
+        with:
+          node-version: ${{ matrix.node-version }}
+      - name: Install module
+        run: npm install
+      - name: Run tests
+        run: npm test
diff --git a/node_modules/busboy/.github/workflows/lint.yml b/node_modules/busboy/.github/workflows/lint.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9f9e1f589a30be583a860f928382b3033c38749d
--- /dev/null
+++ b/node_modules/busboy/.github/workflows/lint.yml
@@ -0,0 +1,23 @@
+name: lint
+
+on:
+  pull_request:
+  push:
+    branches: [ master ]
+
+env:
+  NODE_VERSION: 16.x
+
+jobs:
+  lint-js:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Use Node.js ${{ env.NODE_VERSION }}
+        uses: actions/setup-node@v1
+        with:
+          node-version: ${{ env.NODE_VERSION }}
+      - name: Install ESLint + ESLint configs/plugins
+        run: npm install --only=dev
+      - name: Lint files
+        run: npm run lint
diff --git a/node_modules/busboy/LICENSE b/node_modules/busboy/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..290762e94f4e2f2b52cc13ae4f2b63ac0269bfd1
--- /dev/null
+++ b/node_modules/busboy/LICENSE
@@ -0,0 +1,19 @@
+Copyright Brian White. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/busboy/README.md b/node_modules/busboy/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..654af30455614e47ad22cf53d1235f7c928bf42a
--- /dev/null
+++ b/node_modules/busboy/README.md
@@ -0,0 +1,191 @@
+# Description
+
+A node.js module for parsing incoming HTML form data.
+
+Changes (breaking or otherwise) in v1.0.0 can be found [here](https://github.com/mscdex/busboy/issues/266).
+
+# Requirements
+
+* [node.js](http://nodejs.org/) -- v10.16.0 or newer
+
+
+# Install
+
+    npm install busboy
+
+
+# Examples
+
+* Parsing (multipart) with default options:
+
+```js
+const http = require('http');
+
+const busboy = require('busboy');
+
+http.createServer((req, res) => {
+  if (req.method === 'POST') {
+    console.log('POST request');
+    const bb = busboy({ headers: req.headers });
+    bb.on('file', (name, file, info) => {
+      const { filename, encoding, mimeType } = info;
+      console.log(
+        `File [${name}]: filename: %j, encoding: %j, mimeType: %j`,
+        filename,
+        encoding,
+        mimeType
+      );
+      file.on('data', (data) => {
+        console.log(`File [${name}] got ${data.length} bytes`);
+      }).on('close', () => {
+        console.log(`File [${name}] done`);
+      });
+    });
+    bb.on('field', (name, val, info) => {
+      console.log(`Field [${name}]: value: %j`, val);
+    });
+    bb.on('close', () => {
+      console.log('Done parsing form!');
+      res.writeHead(303, { Connection: 'close', Location: '/' });
+      res.end();
+    });
+    req.pipe(bb);
+  } else if (req.method === 'GET') {
+    res.writeHead(200, { Connection: 'close' });
+    res.end(`
+      <html>
+        <head></head>
+        <body>
+          <form method="POST" enctype="multipart/form-data">
+            <input type="file" name="filefield"><br />
+            <input type="text" name="textfield"><br />
+            <input type="submit">
+          </form>
+        </body>
+      </html>
+    `);
+  }
+}).listen(8000, () => {
+  console.log('Listening for requests');
+});
+
+// Example output:
+//
+// Listening for requests
+//   < ... form submitted ... >
+// POST request
+// File [filefield]: filename: "logo.jpg", encoding: "binary", mime: "image/jpeg"
+// File [filefield] got 11912 bytes
+// Field [textfield]: value: "testing! :-)"
+// File [filefield] done
+// Done parsing form!
+```
+
+* Save all incoming files to disk:
+
+```js
+const { randomFillSync } = require('crypto');
+const fs = require('fs');
+const http = require('http');
+const os = require('os');
+const path = require('path');
+
+const busboy = require('busboy');
+
+const random = (() => {
+  const buf = Buffer.alloc(16);
+  return () => randomFillSync(buf).toString('hex');
+})();
+
+http.createServer((req, res) => {
+  if (req.method === 'POST') {
+    const bb = busboy({ headers: req.headers });
+    bb.on('file', (name, file, info) => {
+      const saveTo = path.join(os.tmpdir(), `busboy-upload-${random()}`);
+      file.pipe(fs.createWriteStream(saveTo));
+    });
+    bb.on('close', () => {
+      res.writeHead(200, { 'Connection': 'close' });
+      res.end(`That's all folks!`);
+    });
+    req.pipe(bb);
+    return;
+  }
+  res.writeHead(404);
+  res.end();
+}).listen(8000, () => {
+  console.log('Listening for requests');
+});
+```
+
+
+# API
+
+## Exports
+
+`busboy` exports a single function:
+
+**( _function_ )**(< _object_ >config) - Creates and returns a new _Writable_ form parser stream.
+
+* Valid `config` properties:
+
+    * **headers** - _object_ - These are the HTTP headers of the incoming request, which are used by individual parsers.
+
+    * **highWaterMark** - _integer_ - highWaterMark to use for the parser stream. **Default:** node's _stream.Writable_ default.
+
+    * **fileHwm** - _integer_ - highWaterMark to use for individual file streams. **Default:** node's _stream.Readable_ default.
+
+    * **defCharset** - _string_ - Default character set to use when one isn't defined. **Default:** `'utf8'`.
+
+    * **defParamCharset** - _string_ - For multipart forms, the default character set to use for values of part header parameters (e.g. filename) that are not extended parameters (that contain an explicit charset). **Default:** `'latin1'`.
+
+    * **preservePath** - _boolean_ - If paths in filenames from file parts in a `'multipart/form-data'` request shall be preserved. **Default:** `false`.
+
+    * **limits** - _object_ - Various limits on incoming data. Valid properties are:
+
+        * **fieldNameSize** - _integer_ - Max field name size (in bytes). **Default:** `100`.
+
+        * **fieldSize** - _integer_ - Max field value size (in bytes). **Default:** `1048576` (1MB).
+
+        * **fields** - _integer_ - Max number of non-file fields. **Default:** `Infinity`.
+
+        * **fileSize** - _integer_ - For multipart forms, the max file size (in bytes). **Default:** `Infinity`.
+
+        * **files** - _integer_ - For multipart forms, the max number of file fields. **Default:** `Infinity`.
+
+        * **parts** - _integer_ - For multipart forms, the max number of parts (fields + files). **Default:** `Infinity`.
+
+        * **headerPairs** - _integer_ - For multipart forms, the max number of header key-value pairs to parse. **Default:** `2000` (same as node's http module).
+
+This function can throw exceptions if there is something wrong with the values in `config`. For example, if the Content-Type in `headers` is missing entirely, is not a supported type, or is missing the boundary for `'multipart/form-data'` requests.
+
+## (Special) Parser stream events
+
+* **file**(< _string_ >name, < _Readable_ >stream, < _object_ >info) - Emitted for each new file found. `name` contains the form field name. `stream` is a _Readable_ stream containing the file's data. No transformations/conversions (e.g. base64 to raw binary) are done on the file's data. `info` contains the following properties:
+
+    * `filename` - _string_ - If supplied, this contains the file's filename. **WARNING:** You should almost _never_ use this value as-is (especially if you are using `preservePath: true` in your `config`) as it could contain malicious input. You are better off generating your own (safe) filenames, or at the very least using a hash of the filename.
+
+    * `encoding` - _string_ - The file's `'Content-Transfer-Encoding'` value.
+
+    * `mimeType` - _string_ - The file's `'Content-Type'` value.
+
+    **Note:** If you listen for this event, you should always consume the `stream` whether you care about its contents or not (you can simply do `stream.resume();` if you want to discard/skip the contents), otherwise the `'finish'`/`'close'` event will never fire on the busboy parser stream.
+    However, if you aren't accepting files, you can either simply not listen for the `'file'` event at all or set `limits.files` to `0`, and any/all files will be automatically skipped (these skipped files will still count towards any configured `limits.files` and `limits.parts` limits though).
+
+    **Note:** If a configured `limits.fileSize` limit was reached for a file, `stream` will both have a boolean property `truncated` set to `true` (best checked at the end of the stream) and emit a `'limit'` event to notify you when this happens.
+
+* **field**(< _string_ >name, < _string_ >value, < _object_ >info) - Emitted for each new non-file field found. `name` contains the form field name. `value` contains the string value of the field. `info` contains the following properties:
+
+    * `nameTruncated` - _boolean_ - Whether `name` was truncated or not (due to a configured `limits.fieldNameSize` limit)
+
+    * `valueTruncated` - _boolean_ - Whether `value` was truncated or not (due to a configured `limits.fieldSize` limit)
+
+    * `encoding` - _string_ - The field's `'Content-Transfer-Encoding'` value.
+
+    * `mimeType` - _string_ - The field's `'Content-Type'` value.
+
+* **partsLimit**() - Emitted when the configured `limits.parts` limit has been reached. No more `'file'` or `'field'` events will be emitted.
+
+* **filesLimit**() - Emitted when the configured `limits.files` limit has been reached. No more `'file'` events will be emitted.
+
+* **fieldsLimit**() - Emitted when the configured `limits.fields` limit has been reached. No more `'field'` events will be emitted.
diff --git a/node_modules/busboy/bench/bench-multipart-fields-100mb-big.js b/node_modules/busboy/bench/bench-multipart-fields-100mb-big.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef15729ea65c38a6c470d7abe63211efb0945c22
--- /dev/null
+++ b/node_modules/busboy/bench/bench-multipart-fields-100mb-big.js
@@ -0,0 +1,149 @@
+'use strict';
+
+function createMultipartBuffers(boundary, sizes) {
+  const bufs = [];
+  for (let i = 0; i < sizes.length; ++i) {
+    const mb = sizes[i] * 1024 * 1024;
+    bufs.push(Buffer.from([
+      `--${boundary}`,
+      `content-disposition: form-data; name="field${i + 1}"`,
+      '',
+      '0'.repeat(mb),
+      '',
+    ].join('\r\n')));
+  }
+  bufs.push(Buffer.from([
+    `--${boundary}--`,
+    '',
+  ].join('\r\n')));
+  return bufs;
+}
+
+const boundary = '-----------------------------168072824752491622650073';
+const buffers = createMultipartBuffers(boundary, [
+  10,
+  10,
+  10,
+  20,
+  50,
+]);
+const calls = {
+  partBegin: 0,
+  headerField: 0,
+  headerValue: 0,
+  headerEnd: 0,
+  headersEnd: 0,
+  partData: 0,
+  partEnd: 0,
+  end: 0,
+};
+
+const moduleName = process.argv[2];
+switch (moduleName) {
+  case 'busboy': {
+    const busboy = require('busboy');
+
+    const parser = busboy({
+      limits: {
+        fieldSizeLimit: Infinity,
+      },
+      headers: {
+        'content-type': `multipart/form-data; boundary=${boundary}`,
+      },
+    });
+    parser.on('field', (name, val, info) => {
+      ++calls.partBegin;
+      ++calls.partData;
+      ++calls.partEnd;
+    }).on('close', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    });
+
+    console.time(moduleName);
+    for (const buf of buffers)
+      parser.write(buf);
+    break;
+  }
+
+  case 'formidable': {
+    const { MultipartParser } = require('formidable');
+
+    const parser = new MultipartParser();
+    parser.initWithBoundary(boundary);
+    parser.on('data', ({ name }) => {
+      ++calls[name];
+      if (name === 'end')
+        console.timeEnd(moduleName);
+    });
+
+    console.time(moduleName);
+    for (const buf of buffers)
+      parser.write(buf);
+
+    break;
+  }
+
+  case 'multiparty': {
+    const { Readable } = require('stream');
+
+    const { Form } = require('multiparty');
+
+    const form = new Form({
+      maxFieldsSize: Infinity,
+      maxFields: Infinity,
+      maxFilesSize: Infinity,
+      autoFields: false,
+      autoFiles: false,
+    });
+
+    const req = new Readable({ read: () => {} });
+    req.headers = {
+      'content-type': `multipart/form-data; boundary=${boundary}`,
+    };
+
+    function hijack(name, fn) {
+      const oldFn = form[name];
+      form[name] = function() {
+        fn();
+        return oldFn.apply(this, arguments);
+      };
+    }
+
+    hijack('onParseHeaderField', () => {
+      ++calls.headerField;
+    });
+    hijack('onParseHeaderValue', () => {
+      ++calls.headerValue;
+    });
+    hijack('onParsePartBegin', () => {
+      ++calls.partBegin;
+    });
+    hijack('onParsePartData', () => {
+      ++calls.partData;
+    });
+    hijack('onParsePartEnd', () => {
+      ++calls.partEnd;
+    });
+
+    form.on('close', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    }).on('part', (p) => p.resume());
+
+    console.time(moduleName);
+    form.parse(req);
+    for (const buf of buffers)
+      req.push(buf);
+    req.push(null);
+
+    break;
+  }
+
+  default:
+    if (moduleName === undefined)
+      console.error('Missing parser module name');
+    else
+      console.error(`Invalid parser module name: ${moduleName}`);
+    process.exit(1);
+}
diff --git a/node_modules/busboy/bench/bench-multipart-fields-100mb-small.js b/node_modules/busboy/bench/bench-multipart-fields-100mb-small.js
new file mode 100644
index 0000000000000000000000000000000000000000..f32d421c735d323b2b0d7ef478b1d612a939b1a5
--- /dev/null
+++ b/node_modules/busboy/bench/bench-multipart-fields-100mb-small.js
@@ -0,0 +1,143 @@
+'use strict';
+
+function createMultipartBuffers(boundary, sizes) {
+  const bufs = [];
+  for (let i = 0; i < sizes.length; ++i) {
+    const mb = sizes[i] * 1024 * 1024;
+    bufs.push(Buffer.from([
+      `--${boundary}`,
+      `content-disposition: form-data; name="field${i + 1}"`,
+      '',
+      '0'.repeat(mb),
+      '',
+    ].join('\r\n')));
+  }
+  bufs.push(Buffer.from([
+    `--${boundary}--`,
+    '',
+  ].join('\r\n')));
+  return bufs;
+}
+
+const boundary = '-----------------------------168072824752491622650073';
+const buffers = createMultipartBuffers(boundary, (new Array(100)).fill(1));
+const calls = {
+  partBegin: 0,
+  headerField: 0,
+  headerValue: 0,
+  headerEnd: 0,
+  headersEnd: 0,
+  partData: 0,
+  partEnd: 0,
+  end: 0,
+};
+
+const moduleName = process.argv[2];
+switch (moduleName) {
+  case 'busboy': {
+    const busboy = require('busboy');
+
+    const parser = busboy({
+      limits: {
+        fieldSizeLimit: Infinity,
+      },
+      headers: {
+        'content-type': `multipart/form-data; boundary=${boundary}`,
+      },
+    });
+    parser.on('field', (name, val, info) => {
+      ++calls.partBegin;
+      ++calls.partData;
+      ++calls.partEnd;
+    }).on('close', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    });
+
+    console.time(moduleName);
+    for (const buf of buffers)
+      parser.write(buf);
+    break;
+  }
+
+  case 'formidable': {
+    const { MultipartParser } = require('formidable');
+
+    const parser = new MultipartParser();
+    parser.initWithBoundary(boundary);
+    parser.on('data', ({ name }) => {
+      ++calls[name];
+      if (name === 'end')
+        console.timeEnd(moduleName);
+    });
+
+    console.time(moduleName);
+    for (const buf of buffers)
+      parser.write(buf);
+
+    break;
+  }
+
+  case 'multiparty': {
+    const { Readable } = require('stream');
+
+    const { Form } = require('multiparty');
+
+    const form = new Form({
+      maxFieldsSize: Infinity,
+      maxFields: Infinity,
+      maxFilesSize: Infinity,
+      autoFields: false,
+      autoFiles: false,
+    });
+
+    const req = new Readable({ read: () => {} });
+    req.headers = {
+      'content-type': `multipart/form-data; boundary=${boundary}`,
+    };
+
+    function hijack(name, fn) {
+      const oldFn = form[name];
+      form[name] = function() {
+        fn();
+        return oldFn.apply(this, arguments);
+      };
+    }
+
+    hijack('onParseHeaderField', () => {
+      ++calls.headerField;
+    });
+    hijack('onParseHeaderValue', () => {
+      ++calls.headerValue;
+    });
+    hijack('onParsePartBegin', () => {
+      ++calls.partBegin;
+    });
+    hijack('onParsePartData', () => {
+      ++calls.partData;
+    });
+    hijack('onParsePartEnd', () => {
+      ++calls.partEnd;
+    });
+
+    form.on('close', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    }).on('part', (p) => p.resume());
+
+    console.time(moduleName);
+    form.parse(req);
+    for (const buf of buffers)
+      req.push(buf);
+    req.push(null);
+
+    break;
+  }
+
+  default:
+    if (moduleName === undefined)
+      console.error('Missing parser module name');
+    else
+      console.error(`Invalid parser module name: ${moduleName}`);
+    process.exit(1);
+}
diff --git a/node_modules/busboy/bench/bench-multipart-files-100mb-big.js b/node_modules/busboy/bench/bench-multipart-files-100mb-big.js
new file mode 100644
index 0000000000000000000000000000000000000000..b46bdee02cdded28483eb8bba655e56695abd6fa
--- /dev/null
+++ b/node_modules/busboy/bench/bench-multipart-files-100mb-big.js
@@ -0,0 +1,154 @@
+'use strict';
+
+function createMultipartBuffers(boundary, sizes) {
+  const bufs = [];
+  for (let i = 0; i < sizes.length; ++i) {
+    const mb = sizes[i] * 1024 * 1024;
+    bufs.push(Buffer.from([
+      `--${boundary}`,
+      `content-disposition: form-data; name="file${i + 1}"; `
+        + `filename="random${i + 1}.bin"`,
+      'content-type: application/octet-stream',
+      '',
+      '0'.repeat(mb),
+      '',
+    ].join('\r\n')));
+  }
+  bufs.push(Buffer.from([
+    `--${boundary}--`,
+    '',
+  ].join('\r\n')));
+  return bufs;
+}
+
+const boundary = '-----------------------------168072824752491622650073';
+const buffers = createMultipartBuffers(boundary, [
+  10,
+  10,
+  10,
+  20,
+  50,
+]);
+const calls = {
+  partBegin: 0,
+  headerField: 0,
+  headerValue: 0,
+  headerEnd: 0,
+  headersEnd: 0,
+  partData: 0,
+  partEnd: 0,
+  end: 0,
+};
+
+const moduleName = process.argv[2];
+switch (moduleName) {
+  case 'busboy': {
+    const busboy = require('busboy');
+
+    const parser = busboy({
+      limits: {
+        fieldSizeLimit: Infinity,
+      },
+      headers: {
+        'content-type': `multipart/form-data; boundary=${boundary}`,
+      },
+    });
+    parser.on('file', (name, stream, info) => {
+      ++calls.partBegin;
+      stream.on('data', (chunk) => {
+        ++calls.partData;
+      }).on('end', () => {
+        ++calls.partEnd;
+      });
+    }).on('close', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    });
+
+    console.time(moduleName);
+    for (const buf of buffers)
+      parser.write(buf);
+    break;
+  }
+
+  case 'formidable': {
+    const { MultipartParser } = require('formidable');
+
+    const parser = new MultipartParser();
+    parser.initWithBoundary(boundary);
+    parser.on('data', ({ name }) => {
+      ++calls[name];
+      if (name === 'end')
+        console.timeEnd(moduleName);
+    });
+
+    console.time(moduleName);
+    for (const buf of buffers)
+      parser.write(buf);
+
+    break;
+  }
+
+  case 'multiparty': {
+    const { Readable } = require('stream');
+
+    const { Form } = require('multiparty');
+
+    const form = new Form({
+      maxFieldsSize: Infinity,
+      maxFields: Infinity,
+      maxFilesSize: Infinity,
+      autoFields: false,
+      autoFiles: false,
+    });
+
+    const req = new Readable({ read: () => {} });
+    req.headers = {
+      'content-type': `multipart/form-data; boundary=${boundary}`,
+    };
+
+    function hijack(name, fn) {
+      const oldFn = form[name];
+      form[name] = function() {
+        fn();
+        return oldFn.apply(this, arguments);
+      };
+    }
+
+    hijack('onParseHeaderField', () => {
+      ++calls.headerField;
+    });
+    hijack('onParseHeaderValue', () => {
+      ++calls.headerValue;
+    });
+    hijack('onParsePartBegin', () => {
+      ++calls.partBegin;
+    });
+    hijack('onParsePartData', () => {
+      ++calls.partData;
+    });
+    hijack('onParsePartEnd', () => {
+      ++calls.partEnd;
+    });
+
+    form.on('close', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    }).on('part', (p) => p.resume());
+
+    console.time(moduleName);
+    form.parse(req);
+    for (const buf of buffers)
+      req.push(buf);
+    req.push(null);
+
+    break;
+  }
+
+  default:
+    if (moduleName === undefined)
+      console.error('Missing parser module name');
+    else
+      console.error(`Invalid parser module name: ${moduleName}`);
+    process.exit(1);
+}
diff --git a/node_modules/busboy/bench/bench-multipart-files-100mb-small.js b/node_modules/busboy/bench/bench-multipart-files-100mb-small.js
new file mode 100644
index 0000000000000000000000000000000000000000..46b5dffb0c74d8e06000f8ee453ecdb4b2d5a0ec
--- /dev/null
+++ b/node_modules/busboy/bench/bench-multipart-files-100mb-small.js
@@ -0,0 +1,148 @@
+'use strict';
+
+function createMultipartBuffers(boundary, sizes) {
+  const bufs = [];
+  for (let i = 0; i < sizes.length; ++i) {
+    const mb = sizes[i] * 1024 * 1024;
+    bufs.push(Buffer.from([
+      `--${boundary}`,
+      `content-disposition: form-data; name="file${i + 1}"; `
+        + `filename="random${i + 1}.bin"`,
+      'content-type: application/octet-stream',
+      '',
+      '0'.repeat(mb),
+      '',
+    ].join('\r\n')));
+  }
+  bufs.push(Buffer.from([
+    `--${boundary}--`,
+    '',
+  ].join('\r\n')));
+  return bufs;
+}
+
+const boundary = '-----------------------------168072824752491622650073';
+const buffers = createMultipartBuffers(boundary, (new Array(100)).fill(1));
+const calls = {
+  partBegin: 0,
+  headerField: 0,
+  headerValue: 0,
+  headerEnd: 0,
+  headersEnd: 0,
+  partData: 0,
+  partEnd: 0,
+  end: 0,
+};
+
+const moduleName = process.argv[2];
+switch (moduleName) {
+  case 'busboy': {
+    const busboy = require('busboy');
+
+    const parser = busboy({
+      limits: {
+        fieldSizeLimit: Infinity,
+      },
+      headers: {
+        'content-type': `multipart/form-data; boundary=${boundary}`,
+      },
+    });
+    parser.on('file', (name, stream, info) => {
+      ++calls.partBegin;
+      stream.on('data', (chunk) => {
+        ++calls.partData;
+      }).on('end', () => {
+        ++calls.partEnd;
+      });
+    }).on('close', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    });
+
+    console.time(moduleName);
+    for (const buf of buffers)
+      parser.write(buf);
+    break;
+  }
+
+  case 'formidable': {
+    const { MultipartParser } = require('formidable');
+
+    const parser = new MultipartParser();
+    parser.initWithBoundary(boundary);
+    parser.on('data', ({ name }) => {
+      ++calls[name];
+      if (name === 'end')
+        console.timeEnd(moduleName);
+    });
+
+    console.time(moduleName);
+    for (const buf of buffers)
+      parser.write(buf);
+
+    break;
+  }
+
+  case 'multiparty': {
+    const { Readable } = require('stream');
+
+    const { Form } = require('multiparty');
+
+    const form = new Form({
+      maxFieldsSize: Infinity,
+      maxFields: Infinity,
+      maxFilesSize: Infinity,
+      autoFields: false,
+      autoFiles: false,
+    });
+
+    const req = new Readable({ read: () => {} });
+    req.headers = {
+      'content-type': `multipart/form-data; boundary=${boundary}`,
+    };
+
+    function hijack(name, fn) {
+      const oldFn = form[name];
+      form[name] = function() {
+        fn();
+        return oldFn.apply(this, arguments);
+      };
+    }
+
+    hijack('onParseHeaderField', () => {
+      ++calls.headerField;
+    });
+    hijack('onParseHeaderValue', () => {
+      ++calls.headerValue;
+    });
+    hijack('onParsePartBegin', () => {
+      ++calls.partBegin;
+    });
+    hijack('onParsePartData', () => {
+      ++calls.partData;
+    });
+    hijack('onParsePartEnd', () => {
+      ++calls.partEnd;
+    });
+
+    form.on('close', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    }).on('part', (p) => p.resume());
+
+    console.time(moduleName);
+    form.parse(req);
+    for (const buf of buffers)
+      req.push(buf);
+    req.push(null);
+
+    break;
+  }
+
+  default:
+    if (moduleName === undefined)
+      console.error('Missing parser module name');
+    else
+      console.error(`Invalid parser module name: ${moduleName}`);
+    process.exit(1);
+}
diff --git a/node_modules/busboy/bench/bench-urlencoded-fields-100pairs-small.js b/node_modules/busboy/bench/bench-urlencoded-fields-100pairs-small.js
new file mode 100644
index 0000000000000000000000000000000000000000..5c337df2ef951f6a36aabac8894211f06573ce6e
--- /dev/null
+++ b/node_modules/busboy/bench/bench-urlencoded-fields-100pairs-small.js
@@ -0,0 +1,101 @@
+'use strict';
+
+const buffers = [
+  Buffer.from(
+    (new Array(100)).fill('').map((_, i) => `key${i}=value${i}`).join('&')
+  ),
+];
+const calls = {
+  field: 0,
+  end: 0,
+};
+
+let n = 3e3;
+
+const moduleName = process.argv[2];
+switch (moduleName) {
+  case 'busboy': {
+    const busboy = require('busboy');
+
+    console.time(moduleName);
+    (function next() {
+      const parser = busboy({
+        limits: {
+          fieldSizeLimit: Infinity,
+        },
+        headers: {
+          'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
+        },
+      });
+      parser.on('field', (name, val, info) => {
+        ++calls.field;
+      }).on('close', () => {
+        ++calls.end;
+        if (--n === 0)
+          console.timeEnd(moduleName);
+        else
+          process.nextTick(next);
+      });
+
+      for (const buf of buffers)
+        parser.write(buf);
+      parser.end();
+    })();
+    break;
+  }
+
+  case 'formidable': {
+    const QuerystringParser =
+      require('formidable/src/parsers/Querystring.js');
+
+    console.time(moduleName);
+    (function next() {
+      const parser = new QuerystringParser();
+      parser.on('data', (obj) => {
+        ++calls.field;
+      }).on('end', () => {
+        ++calls.end;
+        if (--n === 0)
+          console.timeEnd(moduleName);
+        else
+          process.nextTick(next);
+      });
+
+      for (const buf of buffers)
+        parser.write(buf);
+      parser.end();
+    })();
+    break;
+  }
+
+  case 'formidable-streaming': {
+    const QuerystringParser =
+      require('formidable/src/parsers/StreamingQuerystring.js');
+
+    console.time(moduleName);
+    (function next() {
+      const parser = new QuerystringParser();
+      parser.on('data', (obj) => {
+        ++calls.field;
+      }).on('end', () => {
+        ++calls.end;
+        if (--n === 0)
+          console.timeEnd(moduleName);
+        else
+          process.nextTick(next);
+      });
+
+      for (const buf of buffers)
+        parser.write(buf);
+      parser.end();
+    })();
+    break;
+  }
+
+  default:
+    if (moduleName === undefined)
+      console.error('Missing parser module name');
+    else
+      console.error(`Invalid parser module name: ${moduleName}`);
+    process.exit(1);
+}
diff --git a/node_modules/busboy/bench/bench-urlencoded-fields-900pairs-small-alt.js b/node_modules/busboy/bench/bench-urlencoded-fields-900pairs-small-alt.js
new file mode 100644
index 0000000000000000000000000000000000000000..1f5645cb8cc43fb299c3577027b2cf39b5d9c286
--- /dev/null
+++ b/node_modules/busboy/bench/bench-urlencoded-fields-900pairs-small-alt.js
@@ -0,0 +1,84 @@
+'use strict';
+
+const buffers = [
+  Buffer.from(
+    (new Array(900)).fill('').map((_, i) => `key${i}=value${i}`).join('&')
+  ),
+];
+const calls = {
+  field: 0,
+  end: 0,
+};
+
+const moduleName = process.argv[2];
+switch (moduleName) {
+  case 'busboy': {
+    const busboy = require('busboy');
+
+    console.time(moduleName);
+    const parser = busboy({
+      limits: {
+        fieldSizeLimit: Infinity,
+      },
+      headers: {
+        'content-type': 'application/x-www-form-urlencoded; charset=utf-8',
+      },
+    });
+    parser.on('field', (name, val, info) => {
+      ++calls.field;
+    }).on('close', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    });
+
+    for (const buf of buffers)
+      parser.write(buf);
+    parser.end();
+    break;
+  }
+
+  case 'formidable': {
+    const QuerystringParser =
+      require('formidable/src/parsers/Querystring.js');
+
+    console.time(moduleName);
+    const parser = new QuerystringParser();
+    parser.on('data', (obj) => {
+      ++calls.field;
+    }).on('end', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    });
+
+    for (const buf of buffers)
+      parser.write(buf);
+    parser.end();
+    break;
+  }
+
+  case 'formidable-streaming': {
+    const QuerystringParser =
+      require('formidable/src/parsers/StreamingQuerystring.js');
+
+    console.time(moduleName);
+    const parser = new QuerystringParser();
+    parser.on('data', (obj) => {
+      ++calls.field;
+    }).on('end', () => {
+      ++calls.end;
+      console.timeEnd(moduleName);
+    });
+
+    for (const buf of buffers)
+      parser.write(buf);
+    parser.end();
+    break;
+  }
+
+  default:
+    if (moduleName === undefined)
+      console.error('Missing parser module name');
+    else
+      console.error(`Invalid parser module name: ${moduleName}`);
+    process.exit(1);
+}
diff --git a/node_modules/busboy/lib/index.js b/node_modules/busboy/lib/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..873272d93cf34c7d3c973a8204a23f479c36655c
--- /dev/null
+++ b/node_modules/busboy/lib/index.js
@@ -0,0 +1,57 @@
+'use strict';
+
+const { parseContentType } = require('./utils.js');
+
+function getInstance(cfg) {
+  const headers = cfg.headers;
+  const conType = parseContentType(headers['content-type']);
+  if (!conType)
+    throw new Error('Malformed content type');
+
+  for (const type of TYPES) {
+    const matched = type.detect(conType);
+    if (!matched)
+      continue;
+
+    const instanceCfg = {
+      limits: cfg.limits,
+      headers,
+      conType,
+      highWaterMark: undefined,
+      fileHwm: undefined,
+      defCharset: undefined,
+      defParamCharset: undefined,
+      preservePath: false,
+    };
+    if (cfg.highWaterMark)
+      instanceCfg.highWaterMark = cfg.highWaterMark;
+    if (cfg.fileHwm)
+      instanceCfg.fileHwm = cfg.fileHwm;
+    instanceCfg.defCharset = cfg.defCharset;
+    instanceCfg.defParamCharset = cfg.defParamCharset;
+    instanceCfg.preservePath = cfg.preservePath;
+    return new type(instanceCfg);
+  }
+
+  throw new Error(`Unsupported content type: ${headers['content-type']}`);
+}
+
+// Note: types are explicitly listed here for easier bundling
+// See: https://github.com/mscdex/busboy/issues/121
+const TYPES = [
+  require('./types/multipart'),
+  require('./types/urlencoded'),
+].filter(function(typemod) { return typeof typemod.detect === 'function'; });
+
+module.exports = (cfg) => {
+  if (typeof cfg !== 'object' || cfg === null)
+    cfg = {};
+
+  if (typeof cfg.headers !== 'object'
+      || cfg.headers === null
+      || typeof cfg.headers['content-type'] !== 'string') {
+    throw new Error('Missing Content-Type');
+  }
+
+  return getInstance(cfg);
+};
diff --git a/node_modules/busboy/lib/types/multipart.js b/node_modules/busboy/lib/types/multipart.js
new file mode 100644
index 0000000000000000000000000000000000000000..cc0d7bb6638a12cb0572c95d515a10d6ddbb68cb
--- /dev/null
+++ b/node_modules/busboy/lib/types/multipart.js
@@ -0,0 +1,653 @@
+'use strict';
+
+const { Readable, Writable } = require('stream');
+
+const StreamSearch = require('streamsearch');
+
+const {
+  basename,
+  convertToUTF8,
+  getDecoder,
+  parseContentType,
+  parseDisposition,
+} = require('../utils.js');
+
+const BUF_CRLF = Buffer.from('\r\n');
+const BUF_CR = Buffer.from('\r');
+const BUF_DASH = Buffer.from('-');
+
+function noop() {}
+
+const MAX_HEADER_PAIRS = 2000; // From node
+const MAX_HEADER_SIZE = 16 * 1024; // From node (its default value)
+
+const HPARSER_NAME = 0;
+const HPARSER_PRE_OWS = 1;
+const HPARSER_VALUE = 2;
+class HeaderParser {
+  constructor(cb) {
+    this.header = Object.create(null);
+    this.pairCount = 0;
+    this.byteCount = 0;
+    this.state = HPARSER_NAME;
+    this.name = '';
+    this.value = '';
+    this.crlf = 0;
+    this.cb = cb;
+  }
+
+  reset() {
+    this.header = Object.create(null);
+    this.pairCount = 0;
+    this.byteCount = 0;
+    this.state = HPARSER_NAME;
+    this.name = '';
+    this.value = '';
+    this.crlf = 0;
+  }
+
+  push(chunk, pos, end) {
+    let start = pos;
+    while (pos < end) {
+      switch (this.state) {
+        case HPARSER_NAME: {
+          let done = false;
+          for (; pos < end; ++pos) {
+            if (this.byteCount === MAX_HEADER_SIZE)
+              return -1;
+            ++this.byteCount;
+            const code = chunk[pos];
+            if (TOKEN[code] !== 1) {
+              if (code !== 58/* ':' */)
+                return -1;
+              this.name += chunk.latin1Slice(start, pos);
+              if (this.name.length === 0)
+                return -1;
+              ++pos;
+              done = true;
+              this.state = HPARSER_PRE_OWS;
+              break;
+            }
+          }
+          if (!done) {
+            this.name += chunk.latin1Slice(start, pos);
+            break;
+          }
+          // FALLTHROUGH
+        }
+        case HPARSER_PRE_OWS: {
+          // Skip optional whitespace
+          let done = false;
+          for (; pos < end; ++pos) {
+            if (this.byteCount === MAX_HEADER_SIZE)
+              return -1;
+            ++this.byteCount;
+            const code = chunk[pos];
+            if (code !== 32/* ' ' */ && code !== 9/* '\t' */) {
+              start = pos;
+              done = true;
+              this.state = HPARSER_VALUE;
+              break;
+            }
+          }
+          if (!done)
+            break;
+          // FALLTHROUGH
+        }
+        case HPARSER_VALUE:
+          switch (this.crlf) {
+            case 0: // Nothing yet
+              for (; pos < end; ++pos) {
+                if (this.byteCount === MAX_HEADER_SIZE)
+                  return -1;
+                ++this.byteCount;
+                const code = chunk[pos];
+                if (FIELD_VCHAR[code] !== 1) {
+                  if (code !== 13/* '\r' */)
+                    return -1;
+                  ++this.crlf;
+                  break;
+                }
+              }
+              this.value += chunk.latin1Slice(start, pos++);
+              break;
+            case 1: // Received CR
+              if (this.byteCount === MAX_HEADER_SIZE)
+                return -1;
+              ++this.byteCount;
+              if (chunk[pos++] !== 10/* '\n' */)
+                return -1;
+              ++this.crlf;
+              break;
+            case 2: { // Received CR LF
+              if (this.byteCount === MAX_HEADER_SIZE)
+                return -1;
+              ++this.byteCount;
+              const code = chunk[pos];
+              if (code === 32/* ' ' */ || code === 9/* '\t' */) {
+                // Folded value
+                start = pos;
+                this.crlf = 0;
+              } else {
+                if (++this.pairCount < MAX_HEADER_PAIRS) {
+                  this.name = this.name.toLowerCase();
+                  if (this.header[this.name] === undefined)
+                    this.header[this.name] = [this.value];
+                  else
+                    this.header[this.name].push(this.value);
+                }
+                if (code === 13/* '\r' */) {
+                  ++this.crlf;
+                  ++pos;
+                } else {
+                  // Assume start of next header field name
+                  start = pos;
+                  this.crlf = 0;
+                  this.state = HPARSER_NAME;
+                  this.name = '';
+                  this.value = '';
+                }
+              }
+              break;
+            }
+            case 3: { // Received CR LF CR
+              if (this.byteCount === MAX_HEADER_SIZE)
+                return -1;
+              ++this.byteCount;
+              if (chunk[pos++] !== 10/* '\n' */)
+                return -1;
+              // End of header
+              const header = this.header;
+              this.reset();
+              this.cb(header);
+              return pos;
+            }
+          }
+          break;
+      }
+    }
+
+    return pos;
+  }
+}
+
+class FileStream extends Readable {
+  constructor(opts, owner) {
+    super(opts);
+    this.truncated = false;
+    this._readcb = null;
+    this.once('end', () => {
+      // We need to make sure that we call any outstanding _writecb() that is
+      // associated with this file so that processing of the rest of the form
+      // can continue. This may not happen if the file stream ends right after
+      // backpressure kicks in, so we force it here.
+      this._read();
+      if (--owner._fileEndsLeft === 0 && owner._finalcb) {
+        const cb = owner._finalcb;
+        owner._finalcb = null;
+        // Make sure other 'end' event handlers get a chance to be executed
+        // before busboy's 'finish' event is emitted
+        process.nextTick(cb);
+      }
+    });
+  }
+  _read(n) {
+    const cb = this._readcb;
+    if (cb) {
+      this._readcb = null;
+      cb();
+    }
+  }
+}
+
+const ignoreData = {
+  push: (chunk, pos) => {},
+  destroy: () => {},
+};
+
+function callAndUnsetCb(self, err) {
+  const cb = self._writecb;
+  self._writecb = null;
+  if (err)
+    self.destroy(err);
+  else if (cb)
+    cb();
+}
+
+function nullDecoder(val, hint) {
+  return val;
+}
+
+class Multipart extends Writable {
+  constructor(cfg) {
+    const streamOpts = {
+      autoDestroy: true,
+      emitClose: true,
+      highWaterMark: (typeof cfg.highWaterMark === 'number'
+                      ? cfg.highWaterMark
+                      : undefined),
+    };
+    super(streamOpts);
+
+    if (!cfg.conType.params || typeof cfg.conType.params.boundary !== 'string')
+      throw new Error('Multipart: Boundary not found');
+
+    const boundary = cfg.conType.params.boundary;
+    const paramDecoder = (typeof cfg.defParamCharset === 'string'
+                            && cfg.defParamCharset
+                          ? getDecoder(cfg.defParamCharset)
+                          : nullDecoder);
+    const defCharset = (cfg.defCharset || 'utf8');
+    const preservePath = cfg.preservePath;
+    const fileOpts = {
+      autoDestroy: true,
+      emitClose: true,
+      highWaterMark: (typeof cfg.fileHwm === 'number'
+                      ? cfg.fileHwm
+                      : undefined),
+    };
+
+    const limits = cfg.limits;
+    const fieldSizeLimit = (limits && typeof limits.fieldSize === 'number'
+                            ? limits.fieldSize
+                            : 1 * 1024 * 1024);
+    const fileSizeLimit = (limits && typeof limits.fileSize === 'number'
+                           ? limits.fileSize
+                           : Infinity);
+    const filesLimit = (limits && typeof limits.files === 'number'
+                        ? limits.files
+                        : Infinity);
+    const fieldsLimit = (limits && typeof limits.fields === 'number'
+                         ? limits.fields
+                         : Infinity);
+    const partsLimit = (limits && typeof limits.parts === 'number'
+                        ? limits.parts
+                        : Infinity);
+
+    let parts = -1; // Account for initial boundary
+    let fields = 0;
+    let files = 0;
+    let skipPart = false;
+
+    this._fileEndsLeft = 0;
+    this._fileStream = undefined;
+    this._complete = false;
+    let fileSize = 0;
+
+    let field;
+    let fieldSize = 0;
+    let partCharset;
+    let partEncoding;
+    let partType;
+    let partName;
+    let partTruncated = false;
+
+    let hitFilesLimit = false;
+    let hitFieldsLimit = false;
+
+    this._hparser = null;
+    const hparser = new HeaderParser((header) => {
+      this._hparser = null;
+      skipPart = false;
+
+      partType = 'text/plain';
+      partCharset = defCharset;
+      partEncoding = '7bit';
+      partName = undefined;
+      partTruncated = false;
+
+      let filename;
+      if (!header['content-disposition']) {
+        skipPart = true;
+        return;
+      }
+
+      const disp = parseDisposition(header['content-disposition'][0],
+                                    paramDecoder);
+      if (!disp || disp.type !== 'form-data') {
+        skipPart = true;
+        return;
+      }
+
+      if (disp.params) {
+        if (disp.params.name)
+          partName = disp.params.name;
+
+        if (disp.params['filename*'])
+          filename = disp.params['filename*'];
+        else if (disp.params.filename)
+          filename = disp.params.filename;
+
+        if (filename !== undefined && !preservePath)
+          filename = basename(filename);
+      }
+
+      if (header['content-type']) {
+        const conType = parseContentType(header['content-type'][0]);
+        if (conType) {
+          partType = `${conType.type}/${conType.subtype}`;
+          if (conType.params && typeof conType.params.charset === 'string')
+            partCharset = conType.params.charset.toLowerCase();
+        }
+      }
+
+      if (header['content-transfer-encoding'])
+        partEncoding = header['content-transfer-encoding'][0].toLowerCase();
+
+      if (partType === 'application/octet-stream' || filename !== undefined) {
+        // File
+
+        if (files === filesLimit) {
+          if (!hitFilesLimit) {
+            hitFilesLimit = true;
+            this.emit('filesLimit');
+          }
+          skipPart = true;
+          return;
+        }
+        ++files;
+
+        if (this.listenerCount('file') === 0) {
+          skipPart = true;
+          return;
+        }
+
+        fileSize = 0;
+        this._fileStream = new FileStream(fileOpts, this);
+        ++this._fileEndsLeft;
+        this.emit(
+          'file',
+          partName,
+          this._fileStream,
+          { filename,
+            encoding: partEncoding,
+            mimeType: partType }
+        );
+      } else {
+        // Non-file
+
+        if (fields === fieldsLimit) {
+          if (!hitFieldsLimit) {
+            hitFieldsLimit = true;
+            this.emit('fieldsLimit');
+          }
+          skipPart = true;
+          return;
+        }
+        ++fields;
+
+        if (this.listenerCount('field') === 0) {
+          skipPart = true;
+          return;
+        }
+
+        field = [];
+        fieldSize = 0;
+      }
+    });
+
+    let matchPostBoundary = 0;
+    const ssCb = (isMatch, data, start, end, isDataSafe) => {
+retrydata:
+      while (data) {
+        if (this._hparser !== null) {
+          const ret = this._hparser.push(data, start, end);
+          if (ret === -1) {
+            this._hparser = null;
+            hparser.reset();
+            this.emit('error', new Error('Malformed part header'));
+            break;
+          }
+          start = ret;
+        }
+
+        if (start === end)
+          break;
+
+        if (matchPostBoundary !== 0) {
+          if (matchPostBoundary === 1) {
+            switch (data[start]) {
+              case 45: // '-'
+                // Try matching '--' after boundary
+                matchPostBoundary = 2;
+                ++start;
+                break;
+              case 13: // '\r'
+                // Try matching CR LF before header
+                matchPostBoundary = 3;
+                ++start;
+                break;
+              default:
+                matchPostBoundary = 0;
+            }
+            if (start === end)
+              return;
+          }
+
+          if (matchPostBoundary === 2) {
+            matchPostBoundary = 0;
+            if (data[start] === 45/* '-' */) {
+              // End of multipart data
+              this._complete = true;
+              this._bparser = ignoreData;
+              return;
+            }
+            // We saw something other than '-', so put the dash we consumed
+            // "back"
+            const writecb = this._writecb;
+            this._writecb = noop;
+            ssCb(false, BUF_DASH, 0, 1, false);
+            this._writecb = writecb;
+          } else if (matchPostBoundary === 3) {
+            matchPostBoundary = 0;
+            if (data[start] === 10/* '\n' */) {
+              ++start;
+              if (parts >= partsLimit)
+                break;
+              // Prepare the header parser
+              this._hparser = hparser;
+              if (start === end)
+                break;
+              // Process the remaining data as a header
+              continue retrydata;
+            } else {
+              // We saw something other than LF, so put the CR we consumed
+              // "back"
+              const writecb = this._writecb;
+              this._writecb = noop;
+              ssCb(false, BUF_CR, 0, 1, false);
+              this._writecb = writecb;
+            }
+          }
+        }
+
+        if (!skipPart) {
+          if (this._fileStream) {
+            let chunk;
+            const actualLen = Math.min(end - start, fileSizeLimit - fileSize);
+            if (!isDataSafe) {
+              chunk = Buffer.allocUnsafe(actualLen);
+              data.copy(chunk, 0, start, start + actualLen);
+            } else {
+              chunk = data.slice(start, start + actualLen);
+            }
+
+            fileSize += chunk.length;
+            if (fileSize === fileSizeLimit) {
+              if (chunk.length > 0)
+                this._fileStream.push(chunk);
+              this._fileStream.emit('limit');
+              this._fileStream.truncated = true;
+              skipPart = true;
+            } else if (!this._fileStream.push(chunk)) {
+              if (this._writecb)
+                this._fileStream._readcb = this._writecb;
+              this._writecb = null;
+            }
+          } else if (field !== undefined) {
+            let chunk;
+            const actualLen = Math.min(
+              end - start,
+              fieldSizeLimit - fieldSize
+            );
+            if (!isDataSafe) {
+              chunk = Buffer.allocUnsafe(actualLen);
+              data.copy(chunk, 0, start, start + actualLen);
+            } else {
+              chunk = data.slice(start, start + actualLen);
+            }
+
+            fieldSize += actualLen;
+            field.push(chunk);
+            if (fieldSize === fieldSizeLimit) {
+              skipPart = true;
+              partTruncated = true;
+            }
+          }
+        }
+
+        break;
+      }
+
+      if (isMatch) {
+        matchPostBoundary = 1;
+
+        if (this._fileStream) {
+          // End the active file stream if the previous part was a file
+          this._fileStream.push(null);
+          this._fileStream = null;
+        } else if (field !== undefined) {
+          let data;
+          switch (field.length) {
+            case 0:
+              data = '';
+              break;
+            case 1:
+              data = convertToUTF8(field[0], partCharset, 0);
+              break;
+            default:
+              data = convertToUTF8(
+                Buffer.concat(field, fieldSize),
+                partCharset,
+                0
+              );
+          }
+          field = undefined;
+          fieldSize = 0;
+          this.emit(
+            'field',
+            partName,
+            data,
+            { nameTruncated: false,
+              valueTruncated: partTruncated,
+              encoding: partEncoding,
+              mimeType: partType }
+          );
+        }
+
+        if (++parts === partsLimit)
+          this.emit('partsLimit');
+      }
+    };
+    this._bparser = new StreamSearch(`\r\n--${boundary}`, ssCb);
+
+    this._writecb = null;
+    this._finalcb = null;
+
+    // Just in case there is no preamble
+    this.write(BUF_CRLF);
+  }
+
+  static detect(conType) {
+    return (conType.type === 'multipart' && conType.subtype === 'form-data');
+  }
+
+  _write(chunk, enc, cb) {
+    this._writecb = cb;
+    this._bparser.push(chunk, 0);
+    if (this._writecb)
+      callAndUnsetCb(this);
+  }
+
+  _destroy(err, cb) {
+    this._hparser = null;
+    this._bparser = ignoreData;
+    if (!err)
+      err = checkEndState(this);
+    const fileStream = this._fileStream;
+    if (fileStream) {
+      this._fileStream = null;
+      fileStream.destroy(err);
+    }
+    cb(err);
+  }
+
+  _final(cb) {
+    this._bparser.destroy();
+    if (!this._complete)
+      return cb(new Error('Unexpected end of form'));
+    if (this._fileEndsLeft)
+      this._finalcb = finalcb.bind(null, this, cb);
+    else
+      finalcb(this, cb);
+  }
+}
+
+function finalcb(self, cb, err) {
+  if (err)
+    return cb(err);
+  err = checkEndState(self);
+  cb(err);
+}
+
+function checkEndState(self) {
+  if (self._hparser)
+    return new Error('Malformed part header');
+  const fileStream = self._fileStream;
+  if (fileStream) {
+    self._fileStream = null;
+    fileStream.destroy(new Error('Unexpected end of file'));
+  }
+  if (!self._complete)
+    return new Error('Unexpected end of form');
+}
+
+const TOKEN = [
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+];
+
+const FIELD_VCHAR = [
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+];
+
+module.exports = Multipart;
diff --git a/node_modules/busboy/lib/types/urlencoded.js b/node_modules/busboy/lib/types/urlencoded.js
new file mode 100644
index 0000000000000000000000000000000000000000..5c463a25899a72ab94b17f0a29b937e0c0c3ee97
--- /dev/null
+++ b/node_modules/busboy/lib/types/urlencoded.js
@@ -0,0 +1,350 @@
+'use strict';
+
+const { Writable } = require('stream');
+
+const { getDecoder } = require('../utils.js');
+
+class URLEncoded extends Writable {
+  constructor(cfg) {
+    const streamOpts = {
+      autoDestroy: true,
+      emitClose: true,
+      highWaterMark: (typeof cfg.highWaterMark === 'number'
+                      ? cfg.highWaterMark
+                      : undefined),
+    };
+    super(streamOpts);
+
+    let charset = (cfg.defCharset || 'utf8');
+    if (cfg.conType.params && typeof cfg.conType.params.charset === 'string')
+      charset = cfg.conType.params.charset;
+
+    this.charset = charset;
+
+    const limits = cfg.limits;
+    this.fieldSizeLimit = (limits && typeof limits.fieldSize === 'number'
+                           ? limits.fieldSize
+                           : 1 * 1024 * 1024);
+    this.fieldsLimit = (limits && typeof limits.fields === 'number'
+                        ? limits.fields
+                        : Infinity);
+    this.fieldNameSizeLimit = (
+      limits && typeof limits.fieldNameSize === 'number'
+      ? limits.fieldNameSize
+      : 100
+    );
+
+    this._inKey = true;
+    this._keyTrunc = false;
+    this._valTrunc = false;
+    this._bytesKey = 0;
+    this._bytesVal = 0;
+    this._fields = 0;
+    this._key = '';
+    this._val = '';
+    this._byte = -2;
+    this._lastPos = 0;
+    this._encode = 0;
+    this._decoder = getDecoder(charset);
+  }
+
+  static detect(conType) {
+    return (conType.type === 'application'
+            && conType.subtype === 'x-www-form-urlencoded');
+  }
+
+  _write(chunk, enc, cb) {
+    if (this._fields >= this.fieldsLimit)
+      return cb();
+
+    let i = 0;
+    const len = chunk.length;
+    this._lastPos = 0;
+
+    // Check if we last ended mid-percent-encoded byte
+    if (this._byte !== -2) {
+      i = readPctEnc(this, chunk, i, len);
+      if (i === -1)
+        return cb(new Error('Malformed urlencoded form'));
+      if (i >= len)
+        return cb();
+      if (this._inKey)
+        ++this._bytesKey;
+      else
+        ++this._bytesVal;
+    }
+
+main:
+    while (i < len) {
+      if (this._inKey) {
+        // Parsing key
+
+        i = skipKeyBytes(this, chunk, i, len);
+
+        while (i < len) {
+          switch (chunk[i]) {
+            case 61: // '='
+              if (this._lastPos < i)
+                this._key += chunk.latin1Slice(this._lastPos, i);
+              this._lastPos = ++i;
+              this._key = this._decoder(this._key, this._encode);
+              this._encode = 0;
+              this._inKey = false;
+              continue main;
+            case 38: // '&'
+              if (this._lastPos < i)
+                this._key += chunk.latin1Slice(this._lastPos, i);
+              this._lastPos = ++i;
+              this._key = this._decoder(this._key, this._encode);
+              this._encode = 0;
+              if (this._bytesKey > 0) {
+                this.emit(
+                  'field',
+                  this._key,
+                  '',
+                  { nameTruncated: this._keyTrunc,
+                    valueTruncated: false,
+                    encoding: this.charset,
+                    mimeType: 'text/plain' }
+                );
+              }
+              this._key = '';
+              this._val = '';
+              this._keyTrunc = false;
+              this._valTrunc = false;
+              this._bytesKey = 0;
+              this._bytesVal = 0;
+              if (++this._fields >= this.fieldsLimit) {
+                this.emit('fieldsLimit');
+                return cb();
+              }
+              continue;
+            case 43: // '+'
+              if (this._lastPos < i)
+                this._key += chunk.latin1Slice(this._lastPos, i);
+              this._key += ' ';
+              this._lastPos = i + 1;
+              break;
+            case 37: // '%'
+              if (this._encode === 0)
+                this._encode = 1;
+              if (this._lastPos < i)
+                this._key += chunk.latin1Slice(this._lastPos, i);
+              this._lastPos = i + 1;
+              this._byte = -1;
+              i = readPctEnc(this, chunk, i + 1, len);
+              if (i === -1)
+                return cb(new Error('Malformed urlencoded form'));
+              if (i >= len)
+                return cb();
+              ++this._bytesKey;
+              i = skipKeyBytes(this, chunk, i, len);
+              continue;
+          }
+          ++i;
+          ++this._bytesKey;
+          i = skipKeyBytes(this, chunk, i, len);
+        }
+        if (this._lastPos < i)
+          this._key += chunk.latin1Slice(this._lastPos, i);
+      } else {
+        // Parsing value
+
+        i = skipValBytes(this, chunk, i, len);
+
+        while (i < len) {
+          switch (chunk[i]) {
+            case 38: // '&'
+              if (this._lastPos < i)
+                this._val += chunk.latin1Slice(this._lastPos, i);
+              this._lastPos = ++i;
+              this._inKey = true;
+              this._val = this._decoder(this._val, this._encode);
+              this._encode = 0;
+              if (this._bytesKey > 0 || this._bytesVal > 0) {
+                this.emit(
+                  'field',
+                  this._key,
+                  this._val,
+                  { nameTruncated: this._keyTrunc,
+                    valueTruncated: this._valTrunc,
+                    encoding: this.charset,
+                    mimeType: 'text/plain' }
+                );
+              }
+              this._key = '';
+              this._val = '';
+              this._keyTrunc = false;
+              this._valTrunc = false;
+              this._bytesKey = 0;
+              this._bytesVal = 0;
+              if (++this._fields >= this.fieldsLimit) {
+                this.emit('fieldsLimit');
+                return cb();
+              }
+              continue main;
+            case 43: // '+'
+              if (this._lastPos < i)
+                this._val += chunk.latin1Slice(this._lastPos, i);
+              this._val += ' ';
+              this._lastPos = i + 1;
+              break;
+            case 37: // '%'
+              if (this._encode === 0)
+                this._encode = 1;
+              if (this._lastPos < i)
+                this._val += chunk.latin1Slice(this._lastPos, i);
+              this._lastPos = i + 1;
+              this._byte = -1;
+              i = readPctEnc(this, chunk, i + 1, len);
+              if (i === -1)
+                return cb(new Error('Malformed urlencoded form'));
+              if (i >= len)
+                return cb();
+              ++this._bytesVal;
+              i = skipValBytes(this, chunk, i, len);
+              continue;
+          }
+          ++i;
+          ++this._bytesVal;
+          i = skipValBytes(this, chunk, i, len);
+        }
+        if (this._lastPos < i)
+          this._val += chunk.latin1Slice(this._lastPos, i);
+      }
+    }
+
+    cb();
+  }
+
+  _final(cb) {
+    if (this._byte !== -2)
+      return cb(new Error('Malformed urlencoded form'));
+    if (!this._inKey || this._bytesKey > 0 || this._bytesVal > 0) {
+      if (this._inKey)
+        this._key = this._decoder(this._key, this._encode);
+      else
+        this._val = this._decoder(this._val, this._encode);
+      this.emit(
+        'field',
+        this._key,
+        this._val,
+        { nameTruncated: this._keyTrunc,
+          valueTruncated: this._valTrunc,
+          encoding: this.charset,
+          mimeType: 'text/plain' }
+      );
+    }
+    cb();
+  }
+}
+
+function readPctEnc(self, chunk, pos, len) {
+  if (pos >= len)
+    return len;
+
+  if (self._byte === -1) {
+    // We saw a '%' but no hex characters yet
+    const hexUpper = HEX_VALUES[chunk[pos++]];
+    if (hexUpper === -1)
+      return -1;
+
+    if (hexUpper >= 8)
+      self._encode = 2; // Indicate high bits detected
+
+    if (pos < len) {
+      // Both hex characters are in this chunk
+      const hexLower = HEX_VALUES[chunk[pos++]];
+      if (hexLower === -1)
+        return -1;
+
+      if (self._inKey)
+        self._key += String.fromCharCode((hexUpper << 4) + hexLower);
+      else
+        self._val += String.fromCharCode((hexUpper << 4) + hexLower);
+
+      self._byte = -2;
+      self._lastPos = pos;
+    } else {
+      // Only one hex character was available in this chunk
+      self._byte = hexUpper;
+    }
+  } else {
+    // We saw only one hex character so far
+    const hexLower = HEX_VALUES[chunk[pos++]];
+    if (hexLower === -1)
+      return -1;
+
+    if (self._inKey)
+      self._key += String.fromCharCode((self._byte << 4) + hexLower);
+    else
+      self._val += String.fromCharCode((self._byte << 4) + hexLower);
+
+    self._byte = -2;
+    self._lastPos = pos;
+  }
+
+  return pos;
+}
+
+function skipKeyBytes(self, chunk, pos, len) {
+  // Skip bytes if we've truncated
+  if (self._bytesKey > self.fieldNameSizeLimit) {
+    if (!self._keyTrunc) {
+      if (self._lastPos < pos)
+        self._key += chunk.latin1Slice(self._lastPos, pos - 1);
+    }
+    self._keyTrunc = true;
+    for (; pos < len; ++pos) {
+      const code = chunk[pos];
+      if (code === 61/* '=' */ || code === 38/* '&' */)
+        break;
+      ++self._bytesKey;
+    }
+    self._lastPos = pos;
+  }
+
+  return pos;
+}
+
+function skipValBytes(self, chunk, pos, len) {
+  // Skip bytes if we've truncated
+  if (self._bytesVal > self.fieldSizeLimit) {
+    if (!self._valTrunc) {
+      if (self._lastPos < pos)
+        self._val += chunk.latin1Slice(self._lastPos, pos - 1);
+    }
+    self._valTrunc = true;
+    for (; pos < len; ++pos) {
+      if (chunk[pos] === 38/* '&' */)
+        break;
+      ++self._bytesVal;
+    }
+    self._lastPos = pos;
+  }
+
+  return pos;
+}
+
+/* eslint-disable no-multi-spaces */
+const HEX_VALUES = [
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
+  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+];
+/* eslint-enable no-multi-spaces */
+
+module.exports = URLEncoded;
diff --git a/node_modules/busboy/lib/utils.js b/node_modules/busboy/lib/utils.js
new file mode 100644
index 0000000000000000000000000000000000000000..8274f6c3aef47ad929b2e2a4772c23fd6f0644d8
--- /dev/null
+++ b/node_modules/busboy/lib/utils.js
@@ -0,0 +1,596 @@
+'use strict';
+
+function parseContentType(str) {
+  if (str.length === 0)
+    return;
+
+  const params = Object.create(null);
+  let i = 0;
+
+  // Parse type
+  for (; i < str.length; ++i) {
+    const code = str.charCodeAt(i);
+    if (TOKEN[code] !== 1) {
+      if (code !== 47/* '/' */ || i === 0)
+        return;
+      break;
+    }
+  }
+  // Check for type without subtype
+  if (i === str.length)
+    return;
+
+  const type = str.slice(0, i).toLowerCase();
+
+  // Parse subtype
+  const subtypeStart = ++i;
+  for (; i < str.length; ++i) {
+    const code = str.charCodeAt(i);
+    if (TOKEN[code] !== 1) {
+      // Make sure we have a subtype
+      if (i === subtypeStart)
+        return;
+
+      if (parseContentTypeParams(str, i, params) === undefined)
+        return;
+      break;
+    }
+  }
+  // Make sure we have a subtype
+  if (i === subtypeStart)
+    return;
+
+  const subtype = str.slice(subtypeStart, i).toLowerCase();
+
+  return { type, subtype, params };
+}
+
+function parseContentTypeParams(str, i, params) {
+  while (i < str.length) {
+    // Consume whitespace
+    for (; i < str.length; ++i) {
+      const code = str.charCodeAt(i);
+      if (code !== 32/* ' ' */ && code !== 9/* '\t' */)
+        break;
+    }
+
+    // Ended on whitespace
+    if (i === str.length)
+      break;
+
+    // Check for malformed parameter
+    if (str.charCodeAt(i++) !== 59/* ';' */)
+      return;
+
+    // Consume whitespace
+    for (; i < str.length; ++i) {
+      const code = str.charCodeAt(i);
+      if (code !== 32/* ' ' */ && code !== 9/* '\t' */)
+        break;
+    }
+
+    // Ended on whitespace (malformed)
+    if (i === str.length)
+      return;
+
+    let name;
+    const nameStart = i;
+    // Parse parameter name
+    for (; i < str.length; ++i) {
+      const code = str.charCodeAt(i);
+      if (TOKEN[code] !== 1) {
+        if (code !== 61/* '=' */)
+          return;
+        break;
+      }
+    }
+
+    // No value (malformed)
+    if (i === str.length)
+      return;
+
+    name = str.slice(nameStart, i);
+    ++i; // Skip over '='
+
+    // No value (malformed)
+    if (i === str.length)
+      return;
+
+    let value = '';
+    let valueStart;
+    if (str.charCodeAt(i) === 34/* '"' */) {
+      valueStart = ++i;
+      let escaping = false;
+      // Parse quoted value
+      for (; i < str.length; ++i) {
+        const code = str.charCodeAt(i);
+        if (code === 92/* '\\' */) {
+          if (escaping) {
+            valueStart = i;
+            escaping = false;
+          } else {
+            value += str.slice(valueStart, i);
+            escaping = true;
+          }
+          continue;
+        }
+        if (code === 34/* '"' */) {
+          if (escaping) {
+            valueStart = i;
+            escaping = false;
+            continue;
+          }
+          value += str.slice(valueStart, i);
+          break;
+        }
+        if (escaping) {
+          valueStart = i - 1;
+          escaping = false;
+        }
+        // Invalid unescaped quoted character (malformed)
+        if (QDTEXT[code] !== 1)
+          return;
+      }
+
+      // No end quote (malformed)
+      if (i === str.length)
+        return;
+
+      ++i; // Skip over double quote
+    } else {
+      valueStart = i;
+      // Parse unquoted value
+      for (; i < str.length; ++i) {
+        const code = str.charCodeAt(i);
+        if (TOKEN[code] !== 1) {
+          // No value (malformed)
+          if (i === valueStart)
+            return;
+          break;
+        }
+      }
+      value = str.slice(valueStart, i);
+    }
+
+    name = name.toLowerCase();
+    if (params[name] === undefined)
+      params[name] = value;
+  }
+
+  return params;
+}
+
+function parseDisposition(str, defDecoder) {
+  if (str.length === 0)
+    return;
+
+  const params = Object.create(null);
+  let i = 0;
+
+  for (; i < str.length; ++i) {
+    const code = str.charCodeAt(i);
+    if (TOKEN[code] !== 1) {
+      if (parseDispositionParams(str, i, params, defDecoder) === undefined)
+        return;
+      break;
+    }
+  }
+
+  const type = str.slice(0, i).toLowerCase();
+
+  return { type, params };
+}
+
+function parseDispositionParams(str, i, params, defDecoder) {
+  while (i < str.length) {
+    // Consume whitespace
+    for (; i < str.length; ++i) {
+      const code = str.charCodeAt(i);
+      if (code !== 32/* ' ' */ && code !== 9/* '\t' */)
+        break;
+    }
+
+    // Ended on whitespace
+    if (i === str.length)
+      break;
+
+    // Check for malformed parameter
+    if (str.charCodeAt(i++) !== 59/* ';' */)
+      return;
+
+    // Consume whitespace
+    for (; i < str.length; ++i) {
+      const code = str.charCodeAt(i);
+      if (code !== 32/* ' ' */ && code !== 9/* '\t' */)
+        break;
+    }
+
+    // Ended on whitespace (malformed)
+    if (i === str.length)
+      return;
+
+    let name;
+    const nameStart = i;
+    // Parse parameter name
+    for (; i < str.length; ++i) {
+      const code = str.charCodeAt(i);
+      if (TOKEN[code] !== 1) {
+        if (code === 61/* '=' */)
+          break;
+        return;
+      }
+    }
+
+    // No value (malformed)
+    if (i === str.length)
+      return;
+
+    let value = '';
+    let valueStart;
+    let charset;
+    //~ let lang;
+    name = str.slice(nameStart, i);
+    if (name.charCodeAt(name.length - 1) === 42/* '*' */) {
+      // Extended value
+
+      const charsetStart = ++i;
+      // Parse charset name
+      for (; i < str.length; ++i) {
+        const code = str.charCodeAt(i);
+        if (CHARSET[code] !== 1) {
+          if (code !== 39/* '\'' */)
+            return;
+          break;
+        }
+      }
+
+      // Incomplete charset (malformed)
+      if (i === str.length)
+        return;
+
+      charset = str.slice(charsetStart, i);
+      ++i; // Skip over the '\''
+
+      //~ const langStart = ++i;
+      // Parse language name
+      for (; i < str.length; ++i) {
+        const code = str.charCodeAt(i);
+        if (code === 39/* '\'' */)
+          break;
+      }
+
+      // Incomplete language (malformed)
+      if (i === str.length)
+        return;
+
+      //~ lang = str.slice(langStart, i);
+      ++i; // Skip over the '\''
+
+      // No value (malformed)
+      if (i === str.length)
+        return;
+
+      valueStart = i;
+
+      let encode = 0;
+      // Parse value
+      for (; i < str.length; ++i) {
+        const code = str.charCodeAt(i);
+        if (EXTENDED_VALUE[code] !== 1) {
+          if (code === 37/* '%' */) {
+            let hexUpper;
+            let hexLower;
+            if (i + 2 < str.length
+                && (hexUpper = HEX_VALUES[str.charCodeAt(i + 1)]) !== -1
+                && (hexLower = HEX_VALUES[str.charCodeAt(i + 2)]) !== -1) {
+              const byteVal = (hexUpper << 4) + hexLower;
+              value += str.slice(valueStart, i);
+              value += String.fromCharCode(byteVal);
+              i += 2;
+              valueStart = i + 1;
+              if (byteVal >= 128)
+                encode = 2;
+              else if (encode === 0)
+                encode = 1;
+              continue;
+            }
+            // '%' disallowed in non-percent encoded contexts (malformed)
+            return;
+          }
+          break;
+        }
+      }
+
+      value += str.slice(valueStart, i);
+      value = convertToUTF8(value, charset, encode);
+      if (value === undefined)
+        return;
+    } else {
+      // Non-extended value
+
+      ++i; // Skip over '='
+
+      // No value (malformed)
+      if (i === str.length)
+        return;
+
+      if (str.charCodeAt(i) === 34/* '"' */) {
+        valueStart = ++i;
+        let escaping = false;
+        // Parse quoted value
+        for (; i < str.length; ++i) {
+          const code = str.charCodeAt(i);
+          if (code === 92/* '\\' */) {
+            if (escaping) {
+              valueStart = i;
+              escaping = false;
+            } else {
+              value += str.slice(valueStart, i);
+              escaping = true;
+            }
+            continue;
+          }
+          if (code === 34/* '"' */) {
+            if (escaping) {
+              valueStart = i;
+              escaping = false;
+              continue;
+            }
+            value += str.slice(valueStart, i);
+            break;
+          }
+          if (escaping) {
+            valueStart = i - 1;
+            escaping = false;
+          }
+          // Invalid unescaped quoted character (malformed)
+          if (QDTEXT[code] !== 1)
+            return;
+        }
+
+        // No end quote (malformed)
+        if (i === str.length)
+          return;
+
+        ++i; // Skip over double quote
+      } else {
+        valueStart = i;
+        // Parse unquoted value
+        for (; i < str.length; ++i) {
+          const code = str.charCodeAt(i);
+          if (TOKEN[code] !== 1) {
+            // No value (malformed)
+            if (i === valueStart)
+              return;
+            break;
+          }
+        }
+        value = str.slice(valueStart, i);
+      }
+
+      value = defDecoder(value, 2);
+      if (value === undefined)
+        return;
+    }
+
+    name = name.toLowerCase();
+    if (params[name] === undefined)
+      params[name] = value;
+  }
+
+  return params;
+}
+
+function getDecoder(charset) {
+  let lc;
+  while (true) {
+    switch (charset) {
+      case 'utf-8':
+      case 'utf8':
+        return decoders.utf8;
+      case 'latin1':
+      case 'ascii': // TODO: Make these a separate, strict decoder?
+      case 'us-ascii':
+      case 'iso-8859-1':
+      case 'iso8859-1':
+      case 'iso88591':
+      case 'iso_8859-1':
+      case 'windows-1252':
+      case 'iso_8859-1:1987':
+      case 'cp1252':
+      case 'x-cp1252':
+        return decoders.latin1;
+      case 'utf16le':
+      case 'utf-16le':
+      case 'ucs2':
+      case 'ucs-2':
+        return decoders.utf16le;
+      case 'base64':
+        return decoders.base64;
+      default:
+        if (lc === undefined) {
+          lc = true;
+          charset = charset.toLowerCase();
+          continue;
+        }
+        return decoders.other.bind(charset);
+    }
+  }
+}
+
+const decoders = {
+  utf8: (data, hint) => {
+    if (data.length === 0)
+      return '';
+    if (typeof data === 'string') {
+      // If `data` never had any percent-encoded bytes or never had any that
+      // were outside of the ASCII range, then we can safely just return the
+      // input since UTF-8 is ASCII compatible
+      if (hint < 2)
+        return data;
+
+      data = Buffer.from(data, 'latin1');
+    }
+    return data.utf8Slice(0, data.length);
+  },
+
+  latin1: (data, hint) => {
+    if (data.length === 0)
+      return '';
+    if (typeof data === 'string')
+      return data;
+    return data.latin1Slice(0, data.length);
+  },
+
+  utf16le: (data, hint) => {
+    if (data.length === 0)
+      return '';
+    if (typeof data === 'string')
+      data = Buffer.from(data, 'latin1');
+    return data.ucs2Slice(0, data.length);
+  },
+
+  base64: (data, hint) => {
+    if (data.length === 0)
+      return '';
+    if (typeof data === 'string')
+      data = Buffer.from(data, 'latin1');
+    return data.base64Slice(0, data.length);
+  },
+
+  other: (data, hint) => {
+    if (data.length === 0)
+      return '';
+    if (typeof data === 'string')
+      data = Buffer.from(data, 'latin1');
+    try {
+      const decoder = new TextDecoder(this);
+      return decoder.decode(data);
+    } catch {}
+  },
+};
+
+function convertToUTF8(data, charset, hint) {
+  const decode = getDecoder(charset);
+  if (decode)
+    return decode(data, hint);
+}
+
+function basename(path) {
+  if (typeof path !== 'string')
+    return '';
+  for (let i = path.length - 1; i >= 0; --i) {
+    switch (path.charCodeAt(i)) {
+      case 0x2F: // '/'
+      case 0x5C: // '\'
+        path = path.slice(i + 1);
+        return (path === '..' || path === '.' ? '' : path);
+    }
+  }
+  return (path === '..' || path === '.' ? '' : path);
+}
+
+const TOKEN = [
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+];
+
+const QDTEXT = [
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+];
+
+const CHARSET = [
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+];
+
+const EXTENDED_VALUE = [
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+];
+
+/* eslint-disable no-multi-spaces */
+const HEX_VALUES = [
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
+  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+];
+/* eslint-enable no-multi-spaces */
+
+module.exports = {
+  basename,
+  convertToUTF8,
+  getDecoder,
+  parseContentType,
+  parseDisposition,
+};
diff --git a/node_modules/busboy/package.json b/node_modules/busboy/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..ac2577fe2c5873d1f171955eecce4caa5578fdbd
--- /dev/null
+++ b/node_modules/busboy/package.json
@@ -0,0 +1,22 @@
+{ "name": "busboy",
+  "version": "1.6.0",
+  "author": "Brian White <mscdex@mscdex.net>",
+  "description": "A streaming parser for HTML form data for node.js",
+  "main": "./lib/index.js",
+  "dependencies": {
+    "streamsearch": "^1.1.0"
+  },
+  "devDependencies": {
+    "@mscdex/eslint-config": "^1.1.0",
+    "eslint": "^7.32.0"
+  },
+  "scripts": {
+    "test": "node test/test.js",
+    "lint": "eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib test bench",
+    "lint:fix": "npm run lint -- --fix"
+  },
+  "engines": { "node": ">=10.16.0" },
+  "keywords": [ "uploads", "forms", "multipart", "form-data" ],
+  "licenses": [ { "type": "MIT", "url": "http://github.com/mscdex/busboy/raw/master/LICENSE" } ],
+  "repository": { "type": "git", "url": "http://github.com/mscdex/busboy.git" }
+}
diff --git a/node_modules/busboy/test/common.js b/node_modules/busboy/test/common.js
new file mode 100644
index 0000000000000000000000000000000000000000..fb82ad81b1b9ef0e07164e6bfecd8391264ef2c2
--- /dev/null
+++ b/node_modules/busboy/test/common.js
@@ -0,0 +1,109 @@
+'use strict';
+
+const assert = require('assert');
+const { inspect } = require('util');
+
+const mustCallChecks = [];
+
+function noop() {}
+
+function runCallChecks(exitCode) {
+  if (exitCode !== 0) return;
+
+  const failed = mustCallChecks.filter((context) => {
+    if ('minimum' in context) {
+      context.messageSegment = `at least ${context.minimum}`;
+      return context.actual < context.minimum;
+    }
+    context.messageSegment = `exactly ${context.exact}`;
+    return context.actual !== context.exact;
+  });
+
+  failed.forEach((context) => {
+    console.error('Mismatched %s function calls. Expected %s, actual %d.',
+                  context.name,
+                  context.messageSegment,
+                  context.actual);
+    console.error(context.stack.split('\n').slice(2).join('\n'));
+  });
+
+  if (failed.length)
+    process.exit(1);
+}
+
+function mustCall(fn, exact) {
+  return _mustCallInner(fn, exact, 'exact');
+}
+
+function mustCallAtLeast(fn, minimum) {
+  return _mustCallInner(fn, minimum, 'minimum');
+}
+
+function _mustCallInner(fn, criteria = 1, field) {
+  if (process._exiting)
+    throw new Error('Cannot use common.mustCall*() in process exit handler');
+
+  if (typeof fn === 'number') {
+    criteria = fn;
+    fn = noop;
+  } else if (fn === undefined) {
+    fn = noop;
+  }
+
+  if (typeof criteria !== 'number')
+    throw new TypeError(`Invalid ${field} value: ${criteria}`);
+
+  const context = {
+    [field]: criteria,
+    actual: 0,
+    stack: inspect(new Error()),
+    name: fn.name || '<anonymous>'
+  };
+
+  // Add the exit listener only once to avoid listener leak warnings
+  if (mustCallChecks.length === 0)
+    process.on('exit', runCallChecks);
+
+  mustCallChecks.push(context);
+
+  function wrapped(...args) {
+    ++context.actual;
+    return fn.call(this, ...args);
+  }
+  // TODO: remove origFn?
+  wrapped.origFn = fn;
+
+  return wrapped;
+}
+
+function getCallSite(top) {
+  const originalStackFormatter = Error.prepareStackTrace;
+  Error.prepareStackTrace = (err, stack) =>
+    `${stack[0].getFileName()}:${stack[0].getLineNumber()}`;
+  const err = new Error();
+  Error.captureStackTrace(err, top);
+  // With the V8 Error API, the stack is not formatted until it is accessed
+  // eslint-disable-next-line no-unused-expressions
+  err.stack;
+  Error.prepareStackTrace = originalStackFormatter;
+  return err.stack;
+}
+
+function mustNotCall(msg) {
+  const callSite = getCallSite(mustNotCall);
+  return function mustNotCall(...args) {
+    args = args.map(inspect).join(', ');
+    const argsInfo = (args.length > 0
+                      ? `\ncalled with arguments: ${args}`
+                      : '');
+    assert.fail(
+      `${msg || 'function should not have been called'} at ${callSite}`
+        + argsInfo);
+  };
+}
+
+module.exports = {
+  mustCall,
+  mustCallAtLeast,
+  mustNotCall,
+};
diff --git a/node_modules/busboy/test/test-types-multipart-charsets.js b/node_modules/busboy/test/test-types-multipart-charsets.js
new file mode 100644
index 0000000000000000000000000000000000000000..ed9c38aeb6c1f3f85c9eb0efa071349504dbfde6
--- /dev/null
+++ b/node_modules/busboy/test/test-types-multipart-charsets.js
@@ -0,0 +1,94 @@
+'use strict';
+
+const assert = require('assert');
+const { inspect } = require('util');
+
+const { mustCall } = require(`${__dirname}/common.js`);
+
+const busboy = require('..');
+
+const input = Buffer.from([
+  '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+ 'Content-Disposition: form-data; '
+   + 'name="upload_file_0"; filename="テスト.dat"',
+ 'Content-Type: application/octet-stream',
+ '',
+ 'A'.repeat(1023),
+ '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
+].join('\r\n'));
+const boundary = '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k';
+const expected = [
+  { type: 'file',
+    name: 'upload_file_0',
+    data: Buffer.from('A'.repeat(1023)),
+    info: {
+      filename: 'テスト.dat',
+      encoding: '7bit',
+      mimeType: 'application/octet-stream',
+    },
+    limited: false,
+  },
+];
+const bb = busboy({
+  defParamCharset: 'utf8',
+  headers: {
+    'content-type': `multipart/form-data; boundary=${boundary}`,
+  }
+});
+const results = [];
+
+bb.on('field', (name, val, info) => {
+  results.push({ type: 'field', name, val, info });
+});
+
+bb.on('file', (name, stream, info) => {
+  const data = [];
+  let nb = 0;
+  const file = {
+    type: 'file',
+    name,
+    data: null,
+    info,
+    limited: false,
+  };
+  results.push(file);
+  stream.on('data', (d) => {
+    data.push(d);
+    nb += d.length;
+  }).on('limit', () => {
+    file.limited = true;
+  }).on('close', () => {
+    file.data = Buffer.concat(data, nb);
+    assert.strictEqual(stream.truncated, file.limited);
+  }).once('error', (err) => {
+    file.err = err.message;
+  });
+});
+
+bb.on('error', (err) => {
+  results.push({ error: err.message });
+});
+
+bb.on('partsLimit', () => {
+  results.push('partsLimit');
+});
+
+bb.on('filesLimit', () => {
+  results.push('filesLimit');
+});
+
+bb.on('fieldsLimit', () => {
+  results.push('fieldsLimit');
+});
+
+bb.on('close', mustCall(() => {
+  assert.deepStrictEqual(
+    results,
+    expected,
+    'Results mismatch.\n'
+      + `Parsed: ${inspect(results)}\n`
+      + `Expected: ${inspect(expected)}`
+  );
+}));
+
+bb.end(input);
diff --git a/node_modules/busboy/test/test-types-multipart-stream-pause.js b/node_modules/busboy/test/test-types-multipart-stream-pause.js
new file mode 100644
index 0000000000000000000000000000000000000000..df7268a4b17f73af6e1087785e45a8fec2445703
--- /dev/null
+++ b/node_modules/busboy/test/test-types-multipart-stream-pause.js
@@ -0,0 +1,102 @@
+'use strict';
+
+const assert = require('assert');
+const { randomFillSync } = require('crypto');
+const { inspect } = require('util');
+
+const busboy = require('..');
+
+const { mustCall } = require('./common.js');
+
+const BOUNDARY = 'u2KxIV5yF1y+xUspOQCCZopaVgeV6Jxihv35XQJmuTx8X3sh';
+
+function formDataSection(key, value) {
+  return Buffer.from(
+    `\r\n--${BOUNDARY}`
+      + `\r\nContent-Disposition: form-data; name="${key}"`
+      + `\r\n\r\n${value}`
+  );
+}
+
+function formDataFile(key, filename, contentType) {
+  const buf = Buffer.allocUnsafe(100000);
+  return Buffer.concat([
+    Buffer.from(`\r\n--${BOUNDARY}\r\n`),
+    Buffer.from(`Content-Disposition: form-data; name="${key}"`
+                  + `; filename="${filename}"\r\n`),
+    Buffer.from(`Content-Type: ${contentType}\r\n\r\n`),
+    randomFillSync(buf)
+  ]);
+}
+
+const reqChunks = [
+  Buffer.concat([
+    formDataFile('file', 'file.bin', 'application/octet-stream'),
+    formDataSection('foo', 'foo value'),
+  ]),
+  formDataSection('bar', 'bar value'),
+  Buffer.from(`\r\n--${BOUNDARY}--\r\n`)
+];
+const bb = busboy({
+  headers: {
+    'content-type': `multipart/form-data; boundary=${BOUNDARY}`
+  }
+});
+const expected = [
+  { type: 'file',
+    name: 'file',
+    info: {
+      filename: 'file.bin',
+      encoding: '7bit',
+      mimeType: 'application/octet-stream',
+    },
+  },
+  { type: 'field',
+    name: 'foo',
+    val: 'foo value',
+    info: {
+      nameTruncated: false,
+      valueTruncated: false,
+      encoding: '7bit',
+      mimeType: 'text/plain',
+    },
+  },
+  { type: 'field',
+    name: 'bar',
+    val: 'bar value',
+    info: {
+      nameTruncated: false,
+      valueTruncated: false,
+      encoding: '7bit',
+      mimeType: 'text/plain',
+    },
+  },
+];
+const results = [];
+
+bb.on('field', (name, val, info) => {
+  results.push({ type: 'field', name, val, info });
+});
+
+bb.on('file', (name, stream, info) => {
+  results.push({ type: 'file', name, info });
+  // Simulate a pipe where the destination is pausing (perhaps due to waiting
+  // for file system write to finish)
+  setTimeout(() => {
+    stream.resume();
+  }, 10);
+});
+
+bb.on('close', mustCall(() => {
+  assert.deepStrictEqual(
+    results,
+    expected,
+    'Results mismatch.\n'
+      + `Parsed: ${inspect(results)}\n`
+      + `Expected: ${inspect(expected)}`
+  );
+}));
+
+for (const chunk of reqChunks)
+  bb.write(chunk);
+bb.end();
diff --git a/node_modules/busboy/test/test-types-multipart.js b/node_modules/busboy/test/test-types-multipart.js
new file mode 100644
index 0000000000000000000000000000000000000000..9755642ad9060cbcdb2e2e97c1d3b484815d355d
--- /dev/null
+++ b/node_modules/busboy/test/test-types-multipart.js
@@ -0,0 +1,1053 @@
+'use strict';
+
+const assert = require('assert');
+const { inspect } = require('util');
+
+const busboy = require('..');
+
+const active = new Map();
+
+const tests = [
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_0"',
+       '',
+       'super alpha file',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_1"',
+       '',
+       'super beta file',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="1k_a.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'A'.repeat(1023),
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_1"; filename="1k_b.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'B'.repeat(1023),
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { type: 'field',
+        name: 'file_name_0',
+        val: 'super alpha file',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+      { type: 'field',
+        name: 'file_name_1',
+        val: 'super beta file',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('A'.repeat(1023)),
+        info: {
+          filename: '1k_a.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+      },
+      { type: 'file',
+        name: 'upload_file_1',
+        data: Buffer.from('B'.repeat(1023)),
+        info: {
+          filename: '1k_b.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Fields and files'
+  },
+  { source: [
+      ['------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+       'Content-Disposition: form-data; name="cont"',
+       '',
+       'some random content',
+       '------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+       'Content-Disposition: form-data; name="pass"',
+       '',
+       'some random pass',
+       '------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+       'Content-Disposition: form-data; name=bit',
+       '',
+       '2',
+       '------WebKitFormBoundaryTB2MiQ36fnSJlrhY--'
+      ].join('\r\n')
+    ],
+    boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+    expected: [
+      { type: 'field',
+        name: 'cont',
+        val: 'some random content',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+      { type: 'field',
+        name: 'pass',
+        val: 'some random pass',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+      { type: 'field',
+        name: 'bit',
+        val: '2',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+    ],
+    what: 'Fields only'
+  },
+  { source: [
+      ''
+    ],
+    boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+    expected: [
+      { error: 'Unexpected end of form' },
+    ],
+    what: 'No fields and no files'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_0"',
+       '',
+       'super alpha file',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="1k_a.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    limits: {
+      fileSize: 13,
+      fieldSize: 5
+    },
+    expected: [
+      { type: 'field',
+        name: 'file_name_0',
+        val: 'super',
+        info: {
+          nameTruncated: false,
+          valueTruncated: true,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('ABCDEFGHIJKLM'),
+        info: {
+          filename: '1k_a.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: true,
+      },
+    ],
+    what: 'Fields and files (limits)'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_0"',
+       '',
+       'super alpha file',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="1k_a.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    limits: {
+      files: 0
+    },
+    expected: [
+      { type: 'field',
+        name: 'file_name_0',
+        val: 'super alpha file',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+      'filesLimit',
+    ],
+    what: 'Fields and files (limits: 0 files)'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_0"',
+       '',
+       'super alpha file',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_1"',
+       '',
+       'super beta file',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="1k_a.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'A'.repeat(1023),
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_1"; filename="1k_b.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'B'.repeat(1023),
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { type: 'field',
+        name: 'file_name_0',
+        val: 'super alpha file',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+      { type: 'field',
+        name: 'file_name_1',
+        val: 'super beta file',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+    ],
+    events: ['field'],
+    what: 'Fields and (ignored) files'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="/tmp/1k_a.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_1"; filename="C:\\files\\1k_b.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_2"; filename="relative/1k_c.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
+        info: {
+          filename: '1k_a.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+      },
+      { type: 'file',
+        name: 'upload_file_1',
+        data: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
+        info: {
+          filename: '1k_b.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+      },
+      { type: 'file',
+        name: 'upload_file_2',
+        data: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
+        info: {
+          filename: '1k_c.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Files with filenames containing paths'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="/absolute/1k_a.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_1"; filename="C:\\absolute\\1k_b.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_2"; filename="relative/1k_c.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    preservePath: true,
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
+        info: {
+          filename: '/absolute/1k_a.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+      },
+      { type: 'file',
+        name: 'upload_file_1',
+        data: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
+        info: {
+          filename: 'C:\\absolute\\1k_b.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+      },
+      { type: 'file',
+        name: 'upload_file_2',
+        data: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
+        info: {
+          filename: 'relative/1k_c.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Paths to be preserved through the preservePath option'
+  },
+  { source: [
+      ['------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+       'Content-Disposition: form-data; name="cont"',
+       'Content-Type: ',
+       '',
+       'some random content',
+       '------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+       'Content-Disposition: ',
+       '',
+       'some random pass',
+       '------WebKitFormBoundaryTB2MiQ36fnSJlrhY--'
+      ].join('\r\n')
+    ],
+    boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+    expected: [
+      { type: 'field',
+        name: 'cont',
+        val: 'some random content',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+    ],
+    what: 'Empty content-type and empty content-disposition'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="file"; filename*=utf-8\'\'n%C3%A4me.txt',
+       'Content-Type: application/octet-stream',
+       '',
+       'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--'
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { type: 'file',
+        name: 'file',
+        data: Buffer.from('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
+        info: {
+          filename: 'näme.txt',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Unicode filenames'
+  },
+  { source: [
+      ['--asdasdasdasd\r\n',
+       'Content-Type: text/plain\r\n',
+       'Content-Disposition: form-data; name="foo"\r\n',
+       '\r\n',
+       'asd\r\n',
+       '--asdasdasdasd--'
+      ].join(':)')
+    ],
+    boundary: 'asdasdasdasd',
+    expected: [
+      { error: 'Malformed part header' },
+      { error: 'Unexpected end of form' },
+    ],
+    what: 'Stopped mid-header'
+  },
+  { source: [
+      ['------WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+       'Content-Disposition: form-data; name="cont"',
+       'Content-Type: application/json',
+       '',
+       '{}',
+       '------WebKitFormBoundaryTB2MiQ36fnSJlrhY--',
+      ].join('\r\n')
+    ],
+    boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+    expected: [
+      { type: 'field',
+        name: 'cont',
+        val: '{}',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'application/json',
+        },
+      },
+    ],
+    what: 'content-type for fields'
+  },
+  { source: [
+      '------WebKitFormBoundaryTB2MiQ36fnSJlrhY--',
+    ],
+    boundary: '----WebKitFormBoundaryTB2MiQ36fnSJlrhY',
+    expected: [],
+    what: 'empty form'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name=upload_file_0; filename="1k_a.dat"',
+       'Content-Type: application/octet-stream',
+       'Content-Transfer-Encoding: binary',
+       '',
+       '',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.alloc(0),
+        info: {
+          filename: '1k_a.dat',
+          encoding: 'binary',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+        err: 'Unexpected end of form',
+      },
+      { error: 'Unexpected end of form' },
+    ],
+    what: 'Stopped mid-file #1'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name=upload_file_0; filename="1k_a.dat"',
+       'Content-Type: application/octet-stream',
+       '',
+       'a',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('a'),
+        info: {
+          filename: '1k_a.dat',
+          encoding: '7bit',
+          mimeType: 'application/octet-stream',
+        },
+        limited: false,
+        err: 'Unexpected end of form',
+      },
+      { error: 'Unexpected end of form' },
+    ],
+    what: 'Stopped mid-file #2'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="notes.txt"',
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'a',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('a'),
+        info: {
+          filename: 'notes.txt',
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Text file with charset'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="notes.txt"',
+       'Content-Type: ',
+       ' text/plain; charset=utf8',
+       '',
+       'a',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('a'),
+        info: {
+          filename: 'notes.txt',
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Folded header value'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'a',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [],
+    what: 'No Content-Disposition'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_0"',
+       '',
+       'a'.repeat(64 * 1024),
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="notes.txt"',
+       'Content-Type: ',
+       ' text/plain; charset=utf8',
+       '',
+       'bc',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    limits: {
+      fieldSize: Infinity,
+    },
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('bc'),
+        info: {
+          filename: 'notes.txt',
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+        limited: false,
+      },
+    ],
+    events: [ 'file' ],
+    what: 'Skip field parts if no listener'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_0"',
+       '',
+       'a',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="notes.txt"',
+       'Content-Type: ',
+       ' text/plain; charset=utf8',
+       '',
+       'bc',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    limits: {
+      parts: 1,
+    },
+    expected: [
+      { type: 'field',
+        name: 'file_name_0',
+        val: 'a',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+      'partsLimit',
+    ],
+    what: 'Parts limit'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_0"',
+       '',
+       'a',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; name="file_name_1"',
+       '',
+       'b',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    limits: {
+      fields: 1,
+    },
+    expected: [
+      { type: 'field',
+        name: 'file_name_0',
+        val: 'a',
+        info: {
+          nameTruncated: false,
+          valueTruncated: false,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+      },
+      'fieldsLimit',
+    ],
+    what: 'Fields limit'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="notes.txt"',
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'ab',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_1"; filename="notes2.txt"',
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'cd',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    limits: {
+      files: 1,
+    },
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('ab'),
+        info: {
+          filename: 'notes.txt',
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+        limited: false,
+      },
+      'filesLimit',
+    ],
+    what: 'Files limit'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + `name="upload_file_0"; filename="${'a'.repeat(64 * 1024)}.txt"`,
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'ab',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_1"; filename="notes2.txt"',
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'cd',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { error: 'Malformed part header' },
+      { type: 'file',
+        name: 'upload_file_1',
+        data: Buffer.from('cd'),
+        info: {
+          filename: 'notes2.txt',
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Oversized part header'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + 'name="upload_file_0"; filename="notes.txt"',
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'a'.repeat(31) + '\r',
+      ].join('\r\n'),
+      'b'.repeat(40),
+      '\r\n-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    fileHwm: 32,
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('a'.repeat(31) + '\r' + 'b'.repeat(40)),
+        info: {
+          filename: 'notes.txt',
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Lookbehind data should not stall file streams'
+  },
+  { source: [
+      ['-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + `name="upload_file_0"; filename="${'a'.repeat(8 * 1024)}.txt"`,
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'ab',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + `name="upload_file_1"; filename="${'b'.repeat(8 * 1024)}.txt"`,
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'cd',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+       'Content-Disposition: form-data; '
+         + `name="upload_file_2"; filename="${'c'.repeat(8 * 1024)}.txt"`,
+       'Content-Type: text/plain; charset=utf8',
+       '',
+       'ef',
+       '-----------------------------paZqsnEHRufoShdX6fh0lUhXBP4k--',
+      ].join('\r\n')
+    ],
+    boundary: '---------------------------paZqsnEHRufoShdX6fh0lUhXBP4k',
+    expected: [
+      { type: 'file',
+        name: 'upload_file_0',
+        data: Buffer.from('ab'),
+        info: {
+          filename: `${'a'.repeat(8 * 1024)}.txt`,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+        limited: false,
+      },
+      { type: 'file',
+        name: 'upload_file_1',
+        data: Buffer.from('cd'),
+        info: {
+          filename: `${'b'.repeat(8 * 1024)}.txt`,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+        limited: false,
+      },
+      { type: 'file',
+        name: 'upload_file_2',
+        data: Buffer.from('ef'),
+        info: {
+          filename: `${'c'.repeat(8 * 1024)}.txt`,
+          encoding: '7bit',
+          mimeType: 'text/plain',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Header size limit should be per part'
+  },
+  { source: [
+      '\r\n--d1bf46b3-aa33-4061-b28d-6c5ced8b08ee\r\n',
+      'Content-Type: application/gzip\r\n'
+        + 'Content-Encoding: gzip\r\n'
+        + 'Content-Disposition: form-data; name=batch-1; filename=batch-1'
+        + '\r\n\r\n',
+      '\r\n--d1bf46b3-aa33-4061-b28d-6c5ced8b08ee--',
+    ],
+    boundary: 'd1bf46b3-aa33-4061-b28d-6c5ced8b08ee',
+    expected: [
+      { type: 'file',
+        name: 'batch-1',
+        data: Buffer.alloc(0),
+        info: {
+          filename: 'batch-1',
+          encoding: '7bit',
+          mimeType: 'application/gzip',
+        },
+        limited: false,
+      },
+    ],
+    what: 'Empty part'
+  },
+];
+
+for (const test of tests) {
+  active.set(test, 1);
+
+  const { what, boundary, events, limits, preservePath, fileHwm } = test;
+  const bb = busboy({
+    fileHwm,
+    limits,
+    preservePath,
+    headers: {
+      'content-type': `multipart/form-data; boundary=${boundary}`,
+    }
+  });
+  const results = [];
+
+  if (events === undefined || events.includes('field')) {
+    bb.on('field', (name, val, info) => {
+      results.push({ type: 'field', name, val, info });
+    });
+  }
+
+  if (events === undefined || events.includes('file')) {
+    bb.on('file', (name, stream, info) => {
+      const data = [];
+      let nb = 0;
+      const file = {
+        type: 'file',
+        name,
+        data: null,
+        info,
+        limited: false,
+      };
+      results.push(file);
+      stream.on('data', (d) => {
+        data.push(d);
+        nb += d.length;
+      }).on('limit', () => {
+        file.limited = true;
+      }).on('close', () => {
+        file.data = Buffer.concat(data, nb);
+        assert.strictEqual(stream.truncated, file.limited);
+      }).once('error', (err) => {
+        file.err = err.message;
+      });
+    });
+  }
+
+  bb.on('error', (err) => {
+    results.push({ error: err.message });
+  });
+
+  bb.on('partsLimit', () => {
+    results.push('partsLimit');
+  });
+
+  bb.on('filesLimit', () => {
+    results.push('filesLimit');
+  });
+
+  bb.on('fieldsLimit', () => {
+    results.push('fieldsLimit');
+  });
+
+  bb.on('close', () => {
+    active.delete(test);
+
+    assert.deepStrictEqual(
+      results,
+      test.expected,
+      `[${what}] Results mismatch.\n`
+        + `Parsed: ${inspect(results)}\n`
+        + `Expected: ${inspect(test.expected)}`
+    );
+  });
+
+  for (const src of test.source) {
+    const buf = (typeof src === 'string' ? Buffer.from(src, 'utf8') : src);
+    bb.write(buf);
+  }
+  bb.end();
+}
+
+// Byte-by-byte versions
+for (let test of tests) {
+  test = { ...test };
+  test.what += ' (byte-by-byte)';
+  active.set(test, 1);
+
+  const { what, boundary, events, limits, preservePath, fileHwm } = test;
+  const bb = busboy({
+    fileHwm,
+    limits,
+    preservePath,
+    headers: {
+      'content-type': `multipart/form-data; boundary=${boundary}`,
+    }
+  });
+  const results = [];
+
+  if (events === undefined || events.includes('field')) {
+    bb.on('field', (name, val, info) => {
+      results.push({ type: 'field', name, val, info });
+    });
+  }
+
+  if (events === undefined || events.includes('file')) {
+    bb.on('file', (name, stream, info) => {
+      const data = [];
+      let nb = 0;
+      const file = {
+        type: 'file',
+        name,
+        data: null,
+        info,
+        limited: false,
+      };
+      results.push(file);
+      stream.on('data', (d) => {
+        data.push(d);
+        nb += d.length;
+      }).on('limit', () => {
+        file.limited = true;
+      }).on('close', () => {
+        file.data = Buffer.concat(data, nb);
+        assert.strictEqual(stream.truncated, file.limited);
+      }).once('error', (err) => {
+        file.err = err.message;
+      });
+    });
+  }
+
+  bb.on('error', (err) => {
+    results.push({ error: err.message });
+  });
+
+  bb.on('partsLimit', () => {
+    results.push('partsLimit');
+  });
+
+  bb.on('filesLimit', () => {
+    results.push('filesLimit');
+  });
+
+  bb.on('fieldsLimit', () => {
+    results.push('fieldsLimit');
+  });
+
+  bb.on('close', () => {
+    active.delete(test);
+
+    assert.deepStrictEqual(
+      results,
+      test.expected,
+      `[${what}] Results mismatch.\n`
+        + `Parsed: ${inspect(results)}\n`
+        + `Expected: ${inspect(test.expected)}`
+    );
+  });
+
+  for (const src of test.source) {
+    const buf = (typeof src === 'string' ? Buffer.from(src, 'utf8') : src);
+    for (let i = 0; i < buf.length; ++i)
+      bb.write(buf.slice(i, i + 1));
+  }
+  bb.end();
+}
+
+{
+  let exception = false;
+  process.once('uncaughtException', (ex) => {
+    exception = true;
+    throw ex;
+  });
+  process.on('exit', () => {
+    if (exception || active.size === 0)
+      return;
+    process.exitCode = 1;
+    console.error('==========================');
+    console.error(`${active.size} test(s) did not finish:`);
+    console.error('==========================');
+    console.error(Array.from(active.keys()).map((v) => v.what).join('\n'));
+  });
+}
diff --git a/node_modules/busboy/test/test-types-urlencoded.js b/node_modules/busboy/test/test-types-urlencoded.js
new file mode 100644
index 0000000000000000000000000000000000000000..c35962b973f29a69951ed7eae08c0abe6dfbb7da
--- /dev/null
+++ b/node_modules/busboy/test/test-types-urlencoded.js
@@ -0,0 +1,488 @@
+'use strict';
+
+const assert = require('assert');
+const { transcode } = require('buffer');
+const { inspect } = require('util');
+
+const busboy = require('..');
+
+const active = new Map();
+
+const tests = [
+  { source: ['foo'],
+    expected: [
+      ['foo',
+       '',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Unassigned value'
+  },
+  { source: ['foo=bar'],
+    expected: [
+      ['foo',
+       'bar',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Assigned value'
+  },
+  { source: ['foo&bar=baz'],
+    expected: [
+      ['foo',
+       '',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['bar',
+       'baz',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Unassigned and assigned value'
+  },
+  { source: ['foo=bar&baz'],
+    expected: [
+      ['foo',
+       'bar',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['baz',
+       '',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Assigned and unassigned value'
+  },
+  { source: ['foo=bar&baz=bla'],
+    expected: [
+      ['foo',
+       'bar',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['baz',
+       'bla',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Two assigned values'
+  },
+  { source: ['foo&bar'],
+    expected: [
+      ['foo',
+       '',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['bar',
+       '',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Two unassigned values'
+  },
+  { source: ['foo&bar&'],
+    expected: [
+      ['foo',
+       '',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['bar',
+       '',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Two unassigned values and ampersand'
+  },
+  { source: ['foo+1=bar+baz%2Bquux'],
+    expected: [
+      ['foo 1',
+       'bar baz+quux',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Assigned key and value with (plus) space'
+  },
+  { source: ['foo=bar%20baz%21'],
+    expected: [
+      ['foo',
+       'bar baz!',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Assigned value with encoded bytes'
+  },
+  { source: ['foo%20bar=baz%20bla%21'],
+    expected: [
+      ['foo bar',
+       'baz bla!',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Assigned value with encoded bytes #2'
+  },
+  { source: ['foo=bar%20baz%21&num=1000'],
+    expected: [
+      ['foo',
+       'bar baz!',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['num',
+       '1000',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Two assigned values, one with encoded bytes'
+  },
+  { source: [
+      Array.from(transcode(Buffer.from('foo'), 'utf8', 'utf16le')).map(
+        (n) => `%${n.toString(16).padStart(2, '0')}`
+      ).join(''),
+      '=',
+      Array.from(transcode(Buffer.from('😀!'), 'utf8', 'utf16le')).map(
+        (n) => `%${n.toString(16).padStart(2, '0')}`
+      ).join(''),
+    ],
+    expected: [
+      ['foo',
+       '😀!',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'UTF-16LE',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    charset: 'UTF-16LE',
+    what: 'Encoded value with multi-byte charset'
+  },
+  { source: [
+      'foo=<',
+      Array.from(transcode(Buffer.from('©:^þ'), 'utf8', 'latin1')).map(
+        (n) => `%${n.toString(16).padStart(2, '0')}`
+      ).join(''),
+    ],
+    expected: [
+      ['foo',
+       '<©:^þ',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'ISO-8859-1',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    charset: 'ISO-8859-1',
+    what: 'Encoded value with single-byte, ASCII-compatible, non-UTF8 charset'
+  },
+  { source: ['foo=bar&baz=bla'],
+    expected: [],
+    what: 'Limits: zero fields',
+    limits: { fields: 0 }
+  },
+  { source: ['foo=bar&baz=bla'],
+    expected: [
+      ['foo',
+       'bar',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Limits: one field',
+    limits: { fields: 1 }
+  },
+  { source: ['foo=bar&baz=bla'],
+    expected: [
+      ['foo',
+       'bar',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['baz',
+       'bla',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Limits: field part lengths match limits',
+    limits: { fieldNameSize: 3, fieldSize: 3 }
+  },
+  { source: ['foo=bar&baz=bla'],
+    expected: [
+      ['fo',
+       'bar',
+       { nameTruncated: true,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['ba',
+       'bla',
+       { nameTruncated: true,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Limits: truncated field name',
+    limits: { fieldNameSize: 2 }
+  },
+  { source: ['foo=bar&baz=bla'],
+    expected: [
+      ['foo',
+       'ba',
+       { nameTruncated: false,
+         valueTruncated: true,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['baz',
+       'bl',
+       { nameTruncated: false,
+         valueTruncated: true,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Limits: truncated field value',
+    limits: { fieldSize: 2 }
+  },
+  { source: ['foo=bar&baz=bla'],
+    expected: [
+      ['fo',
+       'ba',
+       { nameTruncated: true,
+         valueTruncated: true,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['ba',
+       'bl',
+       { nameTruncated: true,
+         valueTruncated: true,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Limits: truncated field name and value',
+    limits: { fieldNameSize: 2, fieldSize: 2 }
+  },
+  { source: ['foo=bar&baz=bla'],
+    expected: [
+      ['fo',
+       '',
+       { nameTruncated: true,
+         valueTruncated: true,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['ba',
+       '',
+       { nameTruncated: true,
+         valueTruncated: true,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Limits: truncated field name and zero value limit',
+    limits: { fieldNameSize: 2, fieldSize: 0 }
+  },
+  { source: ['foo=bar&baz=bla'],
+    expected: [
+      ['',
+       '',
+       { nameTruncated: true,
+         valueTruncated: true,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+      ['',
+       '',
+       { nameTruncated: true,
+         valueTruncated: true,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Limits: truncated zero field name and zero value limit',
+    limits: { fieldNameSize: 0, fieldSize: 0 }
+  },
+  { source: ['&'],
+    expected: [],
+    what: 'Ampersand'
+  },
+  { source: ['&&&&&'],
+    expected: [],
+    what: 'Many ampersands'
+  },
+  { source: ['='],
+    expected: [
+      ['',
+       '',
+       { nameTruncated: false,
+         valueTruncated: false,
+         encoding: 'utf-8',
+         mimeType: 'text/plain' },
+      ],
+    ],
+    what: 'Assigned value, empty name and value'
+  },
+  { source: [''],
+    expected: [],
+    what: 'Nothing'
+  },
+];
+
+for (const test of tests) {
+  active.set(test, 1);
+
+  const { what } = test;
+  const charset = test.charset || 'utf-8';
+  const bb = busboy({
+    limits: test.limits,
+    headers: {
+      'content-type': `application/x-www-form-urlencoded; charset=${charset}`,
+    },
+  });
+  const results = [];
+
+  bb.on('field', (key, val, info) => {
+    results.push([key, val, info]);
+  });
+
+  bb.on('file', () => {
+    throw new Error(`[${what}] Unexpected file`);
+  });
+
+  bb.on('close', () => {
+    active.delete(test);
+
+    assert.deepStrictEqual(
+      results,
+      test.expected,
+      `[${what}] Results mismatch.\n`
+        + `Parsed: ${inspect(results)}\n`
+        + `Expected: ${inspect(test.expected)}`
+    );
+  });
+
+  for (const src of test.source) {
+    const buf = (typeof src === 'string' ? Buffer.from(src, 'utf8') : src);
+    bb.write(buf);
+  }
+  bb.end();
+}
+
+// Byte-by-byte versions
+for (let test of tests) {
+  test = { ...test };
+  test.what += ' (byte-by-byte)';
+  active.set(test, 1);
+
+  const { what } = test;
+  const charset = test.charset || 'utf-8';
+  const bb = busboy({
+    limits: test.limits,
+    headers: {
+      'content-type': `application/x-www-form-urlencoded; charset="${charset}"`,
+    },
+  });
+  const results = [];
+
+  bb.on('field', (key, val, info) => {
+    results.push([key, val, info]);
+  });
+
+  bb.on('file', () => {
+    throw new Error(`[${what}] Unexpected file`);
+  });
+
+  bb.on('close', () => {
+    active.delete(test);
+
+    assert.deepStrictEqual(
+      results,
+      test.expected,
+      `[${what}] Results mismatch.\n`
+        + `Parsed: ${inspect(results)}\n`
+        + `Expected: ${inspect(test.expected)}`
+    );
+  });
+
+  for (const src of test.source) {
+    const buf = (typeof src === 'string' ? Buffer.from(src, 'utf8') : src);
+    for (let i = 0; i < buf.length; ++i)
+      bb.write(buf.slice(i, i + 1));
+  }
+  bb.end();
+}
+
+{
+  let exception = false;
+  process.once('uncaughtException', (ex) => {
+    exception = true;
+    throw ex;
+  });
+  process.on('exit', () => {
+    if (exception || active.size === 0)
+      return;
+    process.exitCode = 1;
+    console.error('==========================');
+    console.error(`${active.size} test(s) did not finish:`);
+    console.error('==========================');
+    console.error(Array.from(active.keys()).map((v) => v.what).join('\n'));
+  });
+}
diff --git a/node_modules/busboy/test/test.js b/node_modules/busboy/test/test.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0380f29de7842d0f5451b79c93c77067b421324
--- /dev/null
+++ b/node_modules/busboy/test/test.js
@@ -0,0 +1,20 @@
+'use strict';
+
+const { spawnSync } = require('child_process');
+const { readdirSync } = require('fs');
+const { join } = require('path');
+
+const files = readdirSync(__dirname).sort();
+for (const filename of files) {
+  if (filename.startsWith('test-')) {
+    const path = join(__dirname, filename);
+    console.log(`> Running ${filename} ...`);
+    const result = spawnSync(`${process.argv0} ${path}`, {
+      shell: true,
+      stdio: 'inherit',
+      windowsHide: true
+    });
+    if (result.status !== 0)
+      process.exitCode = 1;
+  }
+}
diff --git a/node_modules/chalk/index.d.ts b/node_modules/chalk/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9cd88f38beea8708b25ee3f797ebc453dffa4fb0
--- /dev/null
+++ b/node_modules/chalk/index.d.ts
@@ -0,0 +1,415 @@
+/**
+Basic foreground colors.
+
+[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
+*/
+declare type ForegroundColor =
+	| 'black'
+	| 'red'
+	| 'green'
+	| 'yellow'
+	| 'blue'
+	| 'magenta'
+	| 'cyan'
+	| 'white'
+	| 'gray'
+	| 'grey'
+	| 'blackBright'
+	| 'redBright'
+	| 'greenBright'
+	| 'yellowBright'
+	| 'blueBright'
+	| 'magentaBright'
+	| 'cyanBright'
+	| 'whiteBright';
+
+/**
+Basic background colors.
+
+[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
+*/
+declare type BackgroundColor =
+	| 'bgBlack'
+	| 'bgRed'
+	| 'bgGreen'
+	| 'bgYellow'
+	| 'bgBlue'
+	| 'bgMagenta'
+	| 'bgCyan'
+	| 'bgWhite'
+	| 'bgGray'
+	| 'bgGrey'
+	| 'bgBlackBright'
+	| 'bgRedBright'
+	| 'bgGreenBright'
+	| 'bgYellowBright'
+	| 'bgBlueBright'
+	| 'bgMagentaBright'
+	| 'bgCyanBright'
+	| 'bgWhiteBright';
+
+/**
+Basic colors.
+
+[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
+*/
+declare type Color = ForegroundColor | BackgroundColor;
+
+declare type Modifiers =
+	| 'reset'
+	| 'bold'
+	| 'dim'
+	| 'italic'
+	| 'underline'
+	| 'inverse'
+	| 'hidden'
+	| 'strikethrough'
+	| 'visible';
+
+declare namespace chalk {
+	/**
+	Levels:
+	- `0` - All colors disabled.
+	- `1` - Basic 16 colors support.
+	- `2` - ANSI 256 colors support.
+	- `3` - Truecolor 16 million colors support.
+	*/
+	type Level = 0 | 1 | 2 | 3;
+
+	interface Options {
+		/**
+		Specify the color support for Chalk.
+
+		By default, color support is automatically detected based on the environment.
+
+		Levels:
+		- `0` - All colors disabled.
+		- `1` - Basic 16 colors support.
+		- `2` - ANSI 256 colors support.
+		- `3` - Truecolor 16 million colors support.
+		*/
+		level?: Level;
+	}
+
+	/**
+	Return a new Chalk instance.
+	*/
+	type Instance = new (options?: Options) => Chalk;
+
+	/**
+	Detect whether the terminal supports color.
+	*/
+	interface ColorSupport {
+		/**
+		The color level used by Chalk.
+		*/
+		level: Level;
+
+		/**
+		Return whether Chalk supports basic 16 colors.
+		*/
+		hasBasic: boolean;
+
+		/**
+		Return whether Chalk supports ANSI 256 colors.
+		*/
+		has256: boolean;
+
+		/**
+		Return whether Chalk supports Truecolor 16 million colors.
+		*/
+		has16m: boolean;
+	}
+
+	interface ChalkFunction {
+		/**
+		Use a template string.
+
+		@remarks Template literals are unsupported for nested calls (see [issue #341](https://github.com/chalk/chalk/issues/341))
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		log(chalk`
+		CPU: {red ${cpu.totalPercent}%}
+		RAM: {green ${ram.used / ram.total * 100}%}
+		DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
+		`);
+		```
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		log(chalk.red.bgBlack`2 + 3 = {bold ${2 + 3}}`)
+		```
+		*/
+		(text: TemplateStringsArray, ...placeholders: unknown[]): string;
+
+		(...text: unknown[]): string;
+	}
+
+	interface Chalk extends ChalkFunction {
+		/**
+		Return a new Chalk instance.
+		*/
+		Instance: Instance;
+
+		/**
+		The color support for Chalk.
+
+		By default, color support is automatically detected based on the environment.
+
+		Levels:
+		- `0` - All colors disabled.
+		- `1` - Basic 16 colors support.
+		- `2` - ANSI 256 colors support.
+		- `3` - Truecolor 16 million colors support.
+		*/
+		level: Level;
+
+		/**
+		Use HEX value to set text color.
+
+		@param color - Hexadecimal value representing the desired color.
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		chalk.hex('#DEADED');
+		```
+		*/
+		hex(color: string): Chalk;
+
+		/**
+		Use keyword color value to set text color.
+
+		@param color - Keyword value representing the desired color.
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		chalk.keyword('orange');
+		```
+		*/
+		keyword(color: string): Chalk;
+
+		/**
+		Use RGB values to set text color.
+		*/
+		rgb(red: number, green: number, blue: number): Chalk;
+
+		/**
+		Use HSL values to set text color.
+		*/
+		hsl(hue: number, saturation: number, lightness: number): Chalk;
+
+		/**
+		Use HSV values to set text color.
+		*/
+		hsv(hue: number, saturation: number, value: number): Chalk;
+
+		/**
+		Use HWB values to set text color.
+		*/
+		hwb(hue: number, whiteness: number, blackness: number): Chalk;
+
+		/**
+		Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set text color.
+
+		30 <= code && code < 38 || 90 <= code && code < 98
+		For example, 31 for red, 91 for redBright.
+		*/
+		ansi(code: number): Chalk;
+
+		/**
+		Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
+		*/
+		ansi256(index: number): Chalk;
+
+		/**
+		Use HEX value to set background color.
+
+		@param color - Hexadecimal value representing the desired color.
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		chalk.bgHex('#DEADED');
+		```
+		*/
+		bgHex(color: string): Chalk;
+
+		/**
+		Use keyword color value to set background color.
+
+		@param color - Keyword value representing the desired color.
+
+		@example
+		```
+		import chalk = require('chalk');
+
+		chalk.bgKeyword('orange');
+		```
+		*/
+		bgKeyword(color: string): Chalk;
+
+		/**
+		Use RGB values to set background color.
+		*/
+		bgRgb(red: number, green: number, blue: number): Chalk;
+
+		/**
+		Use HSL values to set background color.
+		*/
+		bgHsl(hue: number, saturation: number, lightness: number): Chalk;
+
+		/**
+		Use HSV values to set background color.
+		*/
+		bgHsv(hue: number, saturation: number, value: number): Chalk;
+
+		/**
+		Use HWB values to set background color.
+		*/
+		bgHwb(hue: number, whiteness: number, blackness: number): Chalk;
+
+		/**
+		Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set background color.
+
+		30 <= code && code < 38 || 90 <= code && code < 98
+		For example, 31 for red, 91 for redBright.
+		Use the foreground code, not the background code (for example, not 41, nor 101).
+		*/
+		bgAnsi(code: number): Chalk;
+
+		/**
+		Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set background color.
+		*/
+		bgAnsi256(index: number): Chalk;
+
+		/**
+		Modifier: Resets the current color chain.
+		*/
+		readonly reset: Chalk;
+
+		/**
+		Modifier: Make text bold.
+		*/
+		readonly bold: Chalk;
+
+		/**
+		Modifier: Emitting only a small amount of light.
+		*/
+		readonly dim: Chalk;
+
+		/**
+		Modifier: Make text italic. (Not widely supported)
+		*/
+		readonly italic: Chalk;
+
+		/**
+		Modifier: Make text underline. (Not widely supported)
+		*/
+		readonly underline: Chalk;
+
+		/**
+		Modifier: Inverse background and foreground colors.
+		*/
+		readonly inverse: Chalk;
+
+		/**
+		Modifier: Prints the text, but makes it invisible.
+		*/
+		readonly hidden: Chalk;
+
+		/**
+		Modifier: Puts a horizontal line through the center of the text. (Not widely supported)
+		*/
+		readonly strikethrough: Chalk;
+
+		/**
+		Modifier: Prints the text only when Chalk has a color support level > 0.
+		Can be useful for things that are purely cosmetic.
+		*/
+		readonly visible: Chalk;
+
+		readonly black: Chalk;
+		readonly red: Chalk;
+		readonly green: Chalk;
+		readonly yellow: Chalk;
+		readonly blue: Chalk;
+		readonly magenta: Chalk;
+		readonly cyan: Chalk;
+		readonly white: Chalk;
+
+		/*
+		Alias for `blackBright`.
+		*/
+		readonly gray: Chalk;
+
+		/*
+		Alias for `blackBright`.
+		*/
+		readonly grey: Chalk;
+
+		readonly blackBright: Chalk;
+		readonly redBright: Chalk;
+		readonly greenBright: Chalk;
+		readonly yellowBright: Chalk;
+		readonly blueBright: Chalk;
+		readonly magentaBright: Chalk;
+		readonly cyanBright: Chalk;
+		readonly whiteBright: Chalk;
+
+		readonly bgBlack: Chalk;
+		readonly bgRed: Chalk;
+		readonly bgGreen: Chalk;
+		readonly bgYellow: Chalk;
+		readonly bgBlue: Chalk;
+		readonly bgMagenta: Chalk;
+		readonly bgCyan: Chalk;
+		readonly bgWhite: Chalk;
+
+		/*
+		Alias for `bgBlackBright`.
+		*/
+		readonly bgGray: Chalk;
+
+		/*
+		Alias for `bgBlackBright`.
+		*/
+		readonly bgGrey: Chalk;
+
+		readonly bgBlackBright: Chalk;
+		readonly bgRedBright: Chalk;
+		readonly bgGreenBright: Chalk;
+		readonly bgYellowBright: Chalk;
+		readonly bgBlueBright: Chalk;
+		readonly bgMagentaBright: Chalk;
+		readonly bgCyanBright: Chalk;
+		readonly bgWhiteBright: Chalk;
+	}
+}
+
+/**
+Main Chalk object that allows to chain styles together.
+Call the last one as a method with a string argument.
+Order doesn't matter, and later styles take precedent in case of a conflict.
+This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
+*/
+declare const chalk: chalk.Chalk & chalk.ChalkFunction & {
+	supportsColor: chalk.ColorSupport | false;
+	Level: chalk.Level;
+	Color: Color;
+	ForegroundColor: ForegroundColor;
+	BackgroundColor: BackgroundColor;
+	Modifiers: Modifiers;
+	stderr: chalk.Chalk & {supportsColor: chalk.ColorSupport | false};
+};
+
+export = chalk;
diff --git a/node_modules/chalk/index.js b/node_modules/chalk/index.js
deleted file mode 100644
index 1cc5fa89a951596647e711d84cf88b1410e4d3ea..0000000000000000000000000000000000000000
--- a/node_modules/chalk/index.js
+++ /dev/null
@@ -1,228 +0,0 @@
-'use strict';
-const escapeStringRegexp = require('escape-string-regexp');
-const ansiStyles = require('ansi-styles');
-const stdoutColor = require('supports-color').stdout;
-
-const template = require('./templates.js');
-
-const isSimpleWindowsTerm = process.platform === 'win32' && !(process.env.TERM || '').toLowerCase().startsWith('xterm');
-
-// `supportsColor.level` → `ansiStyles.color[name]` mapping
-const levelMapping = ['ansi', 'ansi', 'ansi256', 'ansi16m'];
-
-// `color-convert` models to exclude from the Chalk API due to conflicts and such
-const skipModels = new Set(['gray']);
-
-const styles = Object.create(null);
-
-function applyOptions(obj, options) {
-	options = options || {};
-
-	// Detect level if not set manually
-	const scLevel = stdoutColor ? stdoutColor.level : 0;
-	obj.level = options.level === undefined ? scLevel : options.level;
-	obj.enabled = 'enabled' in options ? options.enabled : obj.level > 0;
-}
-
-function Chalk(options) {
-	// We check for this.template here since calling `chalk.constructor()`
-	// by itself will have a `this` of a previously constructed chalk object
-	if (!this || !(this instanceof Chalk) || this.template) {
-		const chalk = {};
-		applyOptions(chalk, options);
-
-		chalk.template = function () {
-			const args = [].slice.call(arguments);
-			return chalkTag.apply(null, [chalk.template].concat(args));
-		};
-
-		Object.setPrototypeOf(chalk, Chalk.prototype);
-		Object.setPrototypeOf(chalk.template, chalk);
-
-		chalk.template.constructor = Chalk;
-
-		return chalk.template;
-	}
-
-	applyOptions(this, options);
-}
-
-// Use bright blue on Windows as the normal blue color is illegible
-if (isSimpleWindowsTerm) {
-	ansiStyles.blue.open = '\u001B[94m';
-}
-
-for (const key of Object.keys(ansiStyles)) {
-	ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
-
-	styles[key] = {
-		get() {
-			const codes = ansiStyles[key];
-			return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, key);
-		}
-	};
-}
-
-styles.visible = {
-	get() {
-		return build.call(this, this._styles || [], true, 'visible');
-	}
-};
-
-ansiStyles.color.closeRe = new RegExp(escapeStringRegexp(ansiStyles.color.close), 'g');
-for (const model of Object.keys(ansiStyles.color.ansi)) {
-	if (skipModels.has(model)) {
-		continue;
-	}
-
-	styles[model] = {
-		get() {
-			const level = this.level;
-			return function () {
-				const open = ansiStyles.color[levelMapping[level]][model].apply(null, arguments);
-				const codes = {
-					open,
-					close: ansiStyles.color.close,
-					closeRe: ansiStyles.color.closeRe
-				};
-				return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
-			};
-		}
-	};
-}
-
-ansiStyles.bgColor.closeRe = new RegExp(escapeStringRegexp(ansiStyles.bgColor.close), 'g');
-for (const model of Object.keys(ansiStyles.bgColor.ansi)) {
-	if (skipModels.has(model)) {
-		continue;
-	}
-
-	const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
-	styles[bgModel] = {
-		get() {
-			const level = this.level;
-			return function () {
-				const open = ansiStyles.bgColor[levelMapping[level]][model].apply(null, arguments);
-				const codes = {
-					open,
-					close: ansiStyles.bgColor.close,
-					closeRe: ansiStyles.bgColor.closeRe
-				};
-				return build.call(this, this._styles ? this._styles.concat(codes) : [codes], this._empty, model);
-			};
-		}
-	};
-}
-
-const proto = Object.defineProperties(() => {}, styles);
-
-function build(_styles, _empty, key) {
-	const builder = function () {
-		return applyStyle.apply(builder, arguments);
-	};
-
-	builder._styles = _styles;
-	builder._empty = _empty;
-
-	const self = this;
-
-	Object.defineProperty(builder, 'level', {
-		enumerable: true,
-		get() {
-			return self.level;
-		},
-		set(level) {
-			self.level = level;
-		}
-	});
-
-	Object.defineProperty(builder, 'enabled', {
-		enumerable: true,
-		get() {
-			return self.enabled;
-		},
-		set(enabled) {
-			self.enabled = enabled;
-		}
-	});
-
-	// See below for fix regarding invisible grey/dim combination on Windows
-	builder.hasGrey = this.hasGrey || key === 'gray' || key === 'grey';
-
-	// `__proto__` is used because we must return a function, but there is
-	// no way to create a function with a different prototype
-	builder.__proto__ = proto; // eslint-disable-line no-proto
-
-	return builder;
-}
-
-function applyStyle() {
-	// Support varags, but simply cast to string in case there's only one arg
-	const args = arguments;
-	const argsLen = args.length;
-	let str = String(arguments[0]);
-
-	if (argsLen === 0) {
-		return '';
-	}
-
-	if (argsLen > 1) {
-		// Don't slice `arguments`, it prevents V8 optimizations
-		for (let a = 1; a < argsLen; a++) {
-			str += ' ' + args[a];
-		}
-	}
-
-	if (!this.enabled || this.level <= 0 || !str) {
-		return this._empty ? '' : str;
-	}
-
-	// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe,
-	// see https://github.com/chalk/chalk/issues/58
-	// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop.
-	const originalDim = ansiStyles.dim.open;
-	if (isSimpleWindowsTerm && this.hasGrey) {
-		ansiStyles.dim.open = '';
-	}
-
-	for (const code of this._styles.slice().reverse()) {
-		// Replace any instances already present with a re-opening code
-		// otherwise only the part of the string until said closing code
-		// will be colored, and the rest will simply be 'plain'.
-		str = code.open + str.replace(code.closeRe, code.open) + code.close;
-
-		// Close the styling before a linebreak and reopen
-		// after next line to fix a bleed issue on macOS
-		// https://github.com/chalk/chalk/pull/92
-		str = str.replace(/\r?\n/g, `${code.close}$&${code.open}`);
-	}
-
-	// Reset the original `dim` if we changed it to work around the Windows dimmed gray issue
-	ansiStyles.dim.open = originalDim;
-
-	return str;
-}
-
-function chalkTag(chalk, strings) {
-	if (!Array.isArray(strings)) {
-		// If chalk() was called by itself or with a string,
-		// return the string itself as a string.
-		return [].slice.call(arguments, 1).join(' ');
-	}
-
-	const args = [].slice.call(arguments, 2);
-	const parts = [strings.raw[0]];
-
-	for (let i = 1; i < strings.length; i++) {
-		parts.push(String(args[i - 1]).replace(/[{}\\]/g, '\\$&'));
-		parts.push(String(strings.raw[i]));
-	}
-
-	return template(chalk, parts.join(''));
-}
-
-Object.defineProperties(Chalk.prototype, styles);
-
-module.exports = Chalk(); // eslint-disable-line new-cap
-module.exports.supportsColor = stdoutColor;
-module.exports.default = module.exports; // For TypeScript
diff --git a/node_modules/chalk/index.js.flow b/node_modules/chalk/index.js.flow
deleted file mode 100644
index 622caaa2e803f3b451f617a391b61383925e05d3..0000000000000000000000000000000000000000
--- a/node_modules/chalk/index.js.flow
+++ /dev/null
@@ -1,93 +0,0 @@
-// @flow strict
-
-type TemplateStringsArray = $ReadOnlyArray<string>;
-
-export type Level = $Values<{
-	None: 0,
-	Basic: 1,
-	Ansi256: 2,
-	TrueColor: 3
-}>;
-
-export type ChalkOptions = {|
-	enabled?: boolean,
-	level?: Level
-|};
-
-export type ColorSupport = {|
-	level: Level,
-	hasBasic: boolean,
-	has256: boolean,
-	has16m: boolean
-|};
-
-export interface Chalk {
-	(...text: string[]): string,
-	(text: TemplateStringsArray, ...placeholders: string[]): string,
-	constructor(options?: ChalkOptions): Chalk,
-	enabled: boolean,
-	level: Level,
-	rgb(r: number, g: number, b: number): Chalk,
-	hsl(h: number, s: number, l: number): Chalk,
-	hsv(h: number, s: number, v: number): Chalk,
-	hwb(h: number, w: number, b: number): Chalk,
-	bgHex(color: string): Chalk,
-	bgKeyword(color: string): Chalk,
-	bgRgb(r: number, g: number, b: number): Chalk,
-	bgHsl(h: number, s: number, l: number): Chalk,
-	bgHsv(h: number, s: number, v: number): Chalk,
-	bgHwb(h: number, w: number, b: number): Chalk,
-	hex(color: string): Chalk,
-	keyword(color: string): Chalk,
-
-	+reset: Chalk,
-	+bold: Chalk,
-	+dim: Chalk,
-	+italic: Chalk,
-	+underline: Chalk,
-	+inverse: Chalk,
-	+hidden: Chalk,
-	+strikethrough: Chalk,
-
-	+visible: Chalk,
-
-	+black: Chalk,
-	+red: Chalk,
-	+green: Chalk,
-	+yellow: Chalk,
-	+blue: Chalk,
-	+magenta: Chalk,
-	+cyan: Chalk,
-	+white: Chalk,
-	+gray: Chalk,
-	+grey: Chalk,
-	+blackBright: Chalk,
-	+redBright: Chalk,
-	+greenBright: Chalk,
-	+yellowBright: Chalk,
-	+blueBright: Chalk,
-	+magentaBright: Chalk,
-	+cyanBright: Chalk,
-	+whiteBright: Chalk,
-
-	+bgBlack: Chalk,
-	+bgRed: Chalk,
-	+bgGreen: Chalk,
-	+bgYellow: Chalk,
-	+bgBlue: Chalk,
-	+bgMagenta: Chalk,
-	+bgCyan: Chalk,
-	+bgWhite: Chalk,
-	+bgBlackBright: Chalk,
-	+bgRedBright: Chalk,
-	+bgGreenBright: Chalk,
-	+bgYellowBright: Chalk,
-	+bgBlueBright: Chalk,
-	+bgMagentaBright: Chalk,
-	+bgCyanBright: Chalk,
-	+bgWhiteBrigh: Chalk,
-
-	supportsColor: ColorSupport
-};
-
-declare module.exports: Chalk;
diff --git a/node_modules/chalk/package.json b/node_modules/chalk/package.json
index bc324685a7625f038c2e960e3aae9580dece77b9..47c23f29068caa951b6f9d2a748fbfc291b6b492 100644
--- a/node_modules/chalk/package.json
+++ b/node_modules/chalk/package.json
@@ -1,22 +1,21 @@
 {
 	"name": "chalk",
-	"version": "2.4.2",
+	"version": "4.1.2",
 	"description": "Terminal string styling done right",
 	"license": "MIT",
 	"repository": "chalk/chalk",
+	"funding": "https://github.com/chalk/chalk?sponsor=1",
+	"main": "source",
 	"engines": {
-		"node": ">=4"
+		"node": ">=10"
 	},
 	"scripts": {
-		"test": "xo && tsc --project types && flow --max-warnings=0 && nyc ava",
-		"bench": "matcha benchmark.js",
-		"coveralls": "nyc report --reporter=text-lcov | coveralls"
+		"test": "xo && nyc ava && tsd",
+		"bench": "matcha benchmark.js"
 	},
 	"files": [
-		"index.js",
-		"templates.js",
-		"types/index.d.ts",
-		"index.js.flow"
+		"source",
+		"index.d.ts"
 	],
 	"keywords": [
 		"color",
@@ -42,30 +41,28 @@
 		"text"
 	],
 	"dependencies": {
-		"ansi-styles": "^3.2.1",
-		"escape-string-regexp": "^1.0.5",
-		"supports-color": "^5.3.0"
+		"ansi-styles": "^4.1.0",
+		"supports-color": "^7.1.0"
 	},
 	"devDependencies": {
-		"ava": "*",
-		"coveralls": "^3.0.0",
-		"execa": "^0.9.0",
-		"flow-bin": "^0.68.0",
-		"import-fresh": "^2.0.0",
+		"ava": "^2.4.0",
+		"coveralls": "^3.0.7",
+		"execa": "^4.0.0",
+		"import-fresh": "^3.1.0",
 		"matcha": "^0.7.0",
-		"nyc": "^11.0.2",
-		"resolve-from": "^4.0.0",
-		"typescript": "^2.5.3",
-		"xo": "*"
+		"nyc": "^15.0.0",
+		"resolve-from": "^5.0.0",
+		"tsd": "^0.7.4",
+		"xo": "^0.28.2"
 	},
-	"types": "types/index.d.ts",
 	"xo": {
-		"envs": [
-			"node",
-			"mocha"
-		],
-		"ignores": [
-			"test/_flow.js"
-		]
+		"rules": {
+			"unicorn/prefer-string-slice": "off",
+			"unicorn/prefer-includes": "off",
+			"@typescript-eslint/member-ordering": "off",
+			"no-redeclare": "off",
+			"unicorn/string-content": "off",
+			"unicorn/better-regex": "off"
+		}
 	}
 }
diff --git a/node_modules/chalk/readme.md b/node_modules/chalk/readme.md
index d298e2c48d64a0ce10744fbae5129782f00d6908..a055d21c97ed7625e06912442db51160c6731329 100644
--- a/node_modules/chalk/readme.md
+++ b/node_modules/chalk/readme.md
@@ -9,12 +9,57 @@
 
 > Terminal string styling done right
 
-[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) [![Mentioned in Awesome Node.js](https://awesome.re/mentioned-badge.svg)](https://github.com/sindresorhus/awesome-nodejs)
-
-### [See what's new in Chalk 2](https://github.com/chalk/chalk/releases/tag/v2.0.0)
-
-<img src="https://cdn.rawgit.com/chalk/ansi-styles/8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" alt="" width="900">
-
+[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg) [![run on repl.it](https://repl.it/badge/github/chalk/chalk)](https://repl.it/github/chalk/chalk)
+
+<img src="https://cdn.jsdelivr.net/gh/chalk/ansi-styles@8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
+
+<br>
+
+---
+
+<div align="center">
+	<p>
+		<p>
+			<sup>
+				Sindre Sorhus' open source work is supported by the community on <a href="https://github.com/sponsors/sindresorhus">GitHub Sponsors</a> and <a href="https://stakes.social/0x44d871aebF0126Bf646753E2C976Aa7e68A66c15">Dev</a>
+			</sup>
+		</p>
+		<sup>Special thanks to:</sup>
+		<br>
+		<br>
+		<a href="https://standardresume.co/tech">
+			<img src="https://sindresorhus.com/assets/thanks/standard-resume-logo.svg" width="160"/>
+		</a>
+		<br>
+		<br>
+		<a href="https://retool.com/?utm_campaign=sindresorhus">
+			<img src="https://sindresorhus.com/assets/thanks/retool-logo.svg" width="230"/>
+		</a>
+		<br>
+		<br>
+		<a href="https://doppler.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=chalk&utm_source=github">
+			<div>
+				<img src="https://dashboard.doppler.com/imgs/logo-long.svg" width="240" alt="Doppler">
+			</div>
+			<b>All your environment variables, in one place</b>
+			<div>
+				<span>Stop struggling with scattered API keys, hacking together home-brewed tools,</span>
+				<br>
+				<span>and avoiding access controls. Keep your team and servers in sync with Doppler.</span>
+			</div>
+		</a>
+		<br>
+		<a href="https://uibakery.io/?utm_source=chalk&utm_medium=sponsor&utm_campaign=github">
+			<div>
+				<img src="https://sindresorhus.com/assets/thanks/uibakery-logo.jpg" width="270" alt="UI Bakery">
+			</div>
+		</a>
+	</p>
+</div>
+
+---
+
+<br>
 
 ## Highlights
 
@@ -26,8 +71,7 @@
 - Doesn't extend `String.prototype`
 - Clean and focused
 - Actively maintained
-- [Used by ~23,000 packages](https://www.npmjs.com/browse/depended/chalk) as of December 31, 2017
-
+- [Used by ~50,000 packages](https://www.npmjs.com/browse/depended/chalk) as of January 1, 2020
 
 ## Install
 
@@ -35,11 +79,6 @@
 $ npm install chalk
 ```
 
-<a href="https://www.patreon.com/sindresorhus">
-	<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
-</a>
-
-
 ## Usage
 
 ```js
@@ -113,7 +152,6 @@ console.log(chalk.green('Hello %s'), name);
 //=> 'Hello Sindre'
 ```
 
-
 ## API
 
 ### chalk.`<style>[.<style>...](string, [string...])`
@@ -124,57 +162,50 @@ Chain [styles](#styles) and call the last one as a method with a string argument
 
 Multiple arguments will be separated by space.
 
-### chalk.enabled
-
-Color support is automatically detected, as is the level (see `chalk.level`). However, if you'd like to simply enable/disable Chalk, you can do so via the `.enabled` property.
-
-Chalk is enabled by default unless explicitly disabled via the constructor or `chalk.level` is `0`.
-
-If you need to change this in a reusable module, create a new instance:
-
-```js
-const ctx = new chalk.constructor({enabled: false});
-```
-
 ### chalk.level
 
+Specifies the level of color support.
+
 Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers.
 
 If you need to change this in a reusable module, create a new instance:
 
 ```js
-const ctx = new chalk.constructor({level: 0});
+const ctx = new chalk.Instance({level: 0});
 ```
 
-Levels are as follows:
-
-0. All colors disabled
-1. Basic color support (16 colors)
-2. 256 color support
-3. Truecolor support (16 million colors)
+| Level | Description |
+| :---: | :--- |
+| `0` | All colors disabled |
+| `1` | Basic color support (16 colors) |
+| `2` | 256 color support |
+| `3` | Truecolor support (16 million colors) |
 
 ### chalk.supportsColor
 
 Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
 
-Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add the environment variable `FORCE_COLOR=1` to forcefully enable color or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
+Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
 
 Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
 
+### chalk.stderr and chalk.stderr.supportsColor
+
+`chalk.stderr` contains a separate instance configured with color support detected for `stderr` stream instead of `stdout`. Override rules from `chalk.supportsColor` apply to this too. `chalk.stderr.supportsColor` is exposed for convenience.
 
 ## Styles
 
 ### Modifiers
 
-- `reset`
-- `bold`
-- `dim`
-- `italic` *(Not widely supported)*
-- `underline`
-- `inverse`
-- `hidden`
-- `strikethrough` *(Not widely supported)*
-- `visible` (Text is emitted only if enabled)
+- `reset` - Resets the current color chain.
+- `bold` - Make text bold.
+- `dim` - Emitting only a small amount of light.
+- `italic` - Make text italic. *(Not widely supported)*
+- `underline` - Make text underline. *(Not widely supported)*
+- `inverse`- Inverse background and foreground colors.
+- `hidden` - Prints the text, but makes it invisible.
+- `strikethrough` - Puts a horizontal line through the center of the text. *(Not widely supported)*
+- `visible`- Prints the text only when Chalk has a color level > 0. Can be useful for things that are purely cosmetic.
 
 ### Colors
 
@@ -182,11 +213,11 @@ Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=
 - `red`
 - `green`
 - `yellow`
-- `blue` *(On Windows the bright version is used since normal blue is illegible)*
+- `blue`
 - `magenta`
 - `cyan`
 - `white`
-- `gray` ("bright black")
+- `blackBright` (alias: `gray`, `grey`)
 - `redBright`
 - `greenBright`
 - `yellowBright`
@@ -205,7 +236,7 @@ Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=
 - `bgMagenta`
 - `bgCyan`
 - `bgWhite`
-- `bgBlackBright`
+- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
 - `bgRedBright`
 - `bgGreenBright`
 - `bgYellowBright`
@@ -214,10 +245,9 @@ Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=
 - `bgCyanBright`
 - `bgWhiteBright`
 
-
 ## Tagged template literal
 
-Chalk can be used as a [tagged template literal](http://exploringjs.com/es6/ch_template-literals.html#_tagged-template-literals).
+Chalk can be used as a [tagged template literal](https://exploringjs.com/es6/ch_template-literals.html#_tagged-template-literals).
 
 ```js
 const chalk = require('chalk');
@@ -226,17 +256,18 @@ const miles = 18;
 const calculateFeet = miles => miles * 5280;
 
 console.log(chalk`
-  There are {bold 5280 feet} in a mile.
-  In {bold ${miles} miles}, there are {green.bold ${calculateFeet(miles)} feet}.
+	There are {bold 5280 feet} in a mile.
+	In {bold ${miles} miles}, there are {green.bold ${calculateFeet(miles)} feet}.
 `);
 ```
 
 Blocks are delimited by an opening curly brace (`{`), a style, some content, and a closing curly brace (`}`).
 
-Template styles are chained exactly like normal Chalk styles. The following two statements are equivalent:
+Template styles are chained exactly like normal Chalk styles. The following three statements are equivalent:
 
 ```js
 console.log(chalk.bold.rgb(10, 100, 200)('Hello!'));
+console.log(chalk.bold.rgb(10, 100, 200)`Hello!`);
 console.log(chalk`{bold.rgb(10,100,200) Hello!}`);
 ```
 
@@ -244,7 +275,6 @@ Note that function styles (`rgb()`, `hsl()`, `keyword()`, etc.) may not contain
 
 All interpolated values (`` chalk`${foo}` ``) are converted to strings via the `.toString()` method. All curly braces (`{` and `}`) in interpolated value strings are escaped.
 
-
 ## 256 and Truecolor color support
 
 Chalk supports 256 colors and [Truecolor](https://gist.github.com/XVilka/8346728) (16 million colors) on supported terminal apps.
@@ -270,20 +300,23 @@ The following color models can be used:
 - [`keyword`](https://www.w3.org/wiki/CSS/Properties/color/keywords) (CSS keywords) - Example: `chalk.keyword('orange').bold('Orange!')`
 - [`hsl`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsl(32, 100, 50).bold('Orange!')`
 - [`hsv`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsv(32, 100, 100).bold('Orange!')`
-- [`hwb`](https://en.wikipedia.org/wiki/HWB_color_model)  - Example: `chalk.hwb(32, 0, 50).bold('Orange!')`
-- `ansi16`
-- `ansi256`
-
+- [`hwb`](https://en.wikipedia.org/wiki/HWB_color_model) - Example: `chalk.hwb(32, 0, 50).bold('Orange!')`
+- [`ansi`](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) - Example: `chalk.ansi(31).bgAnsi(93)('red on yellowBright')`
+- [`ansi256`](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) - Example: `chalk.bgAnsi256(194)('Honeydew, more or less')`
 
 ## Windows
 
-If you're on Windows, do yourself a favor and use [`cmder`](http://cmder.net/) instead of `cmd.exe`.
-
+If you're on Windows, do yourself a favor and use [Windows Terminal](https://github.com/microsoft/terminal) instead of `cmd.exe`.
 
 ## Origin story
 
 [colors.js](https://github.com/Marak/colors.js) used to be the most popular string styling module, but it has serious deficiencies like extending `String.prototype` which causes all kinds of [problems](https://github.com/yeoman/yo/issues/68) and the package is unmaintained. Although there are other packages, they either do too much or not enough. Chalk is a clean and focused alternative.
 
+## chalk for enterprise
+
+Available as part of the Tidelift Subscription.
+
+The maintainers of chalk and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-chalk?utm_source=npm-chalk&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
 
 ## Related
 
@@ -302,13 +335,7 @@ If you're on Windows, do yourself a favor and use [`cmder`](http://cmder.net/) i
 - [chalk-pipe](https://github.com/LitoMore/chalk-pipe) - Create chalk style schemes with simpler style strings
 - [terminal-link](https://github.com/sindresorhus/terminal-link) - Create clickable links in the terminal
 
-
 ## Maintainers
 
 - [Sindre Sorhus](https://github.com/sindresorhus)
 - [Josh Junon](https://github.com/qix-)
-
-
-## License
-
-MIT
diff --git a/node_modules/chalk/source/index.js b/node_modules/chalk/source/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..75ec66350527a8f4040671c72760238e6d80b976
--- /dev/null
+++ b/node_modules/chalk/source/index.js
@@ -0,0 +1,229 @@
+'use strict';
+const ansiStyles = require('ansi-styles');
+const {stdout: stdoutColor, stderr: stderrColor} = require('supports-color');
+const {
+	stringReplaceAll,
+	stringEncaseCRLFWithFirstIndex
+} = require('./util');
+
+const {isArray} = Array;
+
+// `supportsColor.level` → `ansiStyles.color[name]` mapping
+const levelMapping = [
+	'ansi',
+	'ansi',
+	'ansi256',
+	'ansi16m'
+];
+
+const styles = Object.create(null);
+
+const applyOptions = (object, options = {}) => {
+	if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
+		throw new Error('The `level` option should be an integer from 0 to 3');
+	}
+
+	// Detect level if not set manually
+	const colorLevel = stdoutColor ? stdoutColor.level : 0;
+	object.level = options.level === undefined ? colorLevel : options.level;
+};
+
+class ChalkClass {
+	constructor(options) {
+		// eslint-disable-next-line no-constructor-return
+		return chalkFactory(options);
+	}
+}
+
+const chalkFactory = options => {
+	const chalk = {};
+	applyOptions(chalk, options);
+
+	chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_);
+
+	Object.setPrototypeOf(chalk, Chalk.prototype);
+	Object.setPrototypeOf(chalk.template, chalk);
+
+	chalk.template.constructor = () => {
+		throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.');
+	};
+
+	chalk.template.Instance = ChalkClass;
+
+	return chalk.template;
+};
+
+function Chalk(options) {
+	return chalkFactory(options);
+}
+
+for (const [styleName, style] of Object.entries(ansiStyles)) {
+	styles[styleName] = {
+		get() {
+			const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty);
+			Object.defineProperty(this, styleName, {value: builder});
+			return builder;
+		}
+	};
+}
+
+styles.visible = {
+	get() {
+		const builder = createBuilder(this, this._styler, true);
+		Object.defineProperty(this, 'visible', {value: builder});
+		return builder;
+	}
+};
+
+const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256'];
+
+for (const model of usedModels) {
+	styles[model] = {
+		get() {
+			const {level} = this;
+			return function (...arguments_) {
+				const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler);
+				return createBuilder(this, styler, this._isEmpty);
+			};
+		}
+	};
+}
+
+for (const model of usedModels) {
+	const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
+	styles[bgModel] = {
+		get() {
+			const {level} = this;
+			return function (...arguments_) {
+				const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler);
+				return createBuilder(this, styler, this._isEmpty);
+			};
+		}
+	};
+}
+
+const proto = Object.defineProperties(() => {}, {
+	...styles,
+	level: {
+		enumerable: true,
+		get() {
+			return this._generator.level;
+		},
+		set(level) {
+			this._generator.level = level;
+		}
+	}
+});
+
+const createStyler = (open, close, parent) => {
+	let openAll;
+	let closeAll;
+	if (parent === undefined) {
+		openAll = open;
+		closeAll = close;
+	} else {
+		openAll = parent.openAll + open;
+		closeAll = close + parent.closeAll;
+	}
+
+	return {
+		open,
+		close,
+		openAll,
+		closeAll,
+		parent
+	};
+};
+
+const createBuilder = (self, _styler, _isEmpty) => {
+	const builder = (...arguments_) => {
+		if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) {
+			// Called as a template literal, for example: chalk.red`2 + 3 = {bold ${2+3}}`
+			return applyStyle(builder, chalkTag(builder, ...arguments_));
+		}
+
+		// Single argument is hot path, implicit coercion is faster than anything
+		// eslint-disable-next-line no-implicit-coercion
+		return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
+	};
+
+	// We alter the prototype because we must return a function, but there is
+	// no way to create a function with a different prototype
+	Object.setPrototypeOf(builder, proto);
+
+	builder._generator = self;
+	builder._styler = _styler;
+	builder._isEmpty = _isEmpty;
+
+	return builder;
+};
+
+const applyStyle = (self, string) => {
+	if (self.level <= 0 || !string) {
+		return self._isEmpty ? '' : string;
+	}
+
+	let styler = self._styler;
+
+	if (styler === undefined) {
+		return string;
+	}
+
+	const {openAll, closeAll} = styler;
+	if (string.indexOf('\u001B') !== -1) {
+		while (styler !== undefined) {
+			// Replace any instances already present with a re-opening code
+			// otherwise only the part of the string until said closing code
+			// will be colored, and the rest will simply be 'plain'.
+			string = stringReplaceAll(string, styler.close, styler.open);
+
+			styler = styler.parent;
+		}
+	}
+
+	// We can move both next actions out of loop, because remaining actions in loop won't have
+	// any/visible effect on parts we add here. Close the styling before a linebreak and reopen
+	// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92
+	const lfIndex = string.indexOf('\n');
+	if (lfIndex !== -1) {
+		string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
+	}
+
+	return openAll + string + closeAll;
+};
+
+let template;
+const chalkTag = (chalk, ...strings) => {
+	const [firstString] = strings;
+
+	if (!isArray(firstString) || !isArray(firstString.raw)) {
+		// If chalk() was called by itself or with a string,
+		// return the string itself as a string.
+		return strings.join(' ');
+	}
+
+	const arguments_ = strings.slice(1);
+	const parts = [firstString.raw[0]];
+
+	for (let i = 1; i < firstString.length; i++) {
+		parts.push(
+			String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'),
+			String(firstString.raw[i])
+		);
+	}
+
+	if (template === undefined) {
+		template = require('./templates');
+	}
+
+	return template(chalk, parts.join(''));
+};
+
+Object.defineProperties(Chalk.prototype, styles);
+
+const chalk = Chalk(); // eslint-disable-line new-cap
+chalk.supportsColor = stdoutColor;
+chalk.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap
+chalk.stderr.supportsColor = stderrColor;
+
+module.exports = chalk;
diff --git a/node_modules/chalk/templates.js b/node_modules/chalk/source/templates.js
similarity index 53%
rename from node_modules/chalk/templates.js
rename to node_modules/chalk/source/templates.js
index dbdf9b221129e40b4828c503b18b3c1b5ff29d97..b130949d646fdad3f5bb493b74dc69baa7eb5d92 100644
--- a/node_modules/chalk/templates.js
+++ b/node_modules/chalk/source/templates.js
@@ -1,8 +1,8 @@
 'use strict';
-const TEMPLATE_REGEX = /(?:\\(u[a-f\d]{4}|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
+const TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
 const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g;
 const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/;
-const ESCAPE_REGEX = /\\(u[a-f\d]{4}|x[a-f\d]{2}|.)|([^\\])/gi;
+const ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi;
 
 const ESCAPES = new Map([
 	['n', '\n'],
@@ -18,23 +18,31 @@ const ESCAPES = new Map([
 ]);
 
 function unescape(c) {
-	if ((c[0] === 'u' && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
+	const u = c[0] === 'u';
+	const bracket = c[1] === '{';
+
+	if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
 		return String.fromCharCode(parseInt(c.slice(1), 16));
 	}
 
+	if (u && bracket) {
+		return String.fromCodePoint(parseInt(c.slice(2, -1), 16));
+	}
+
 	return ESCAPES.get(c) || c;
 }
 
-function parseArguments(name, args) {
+function parseArguments(name, arguments_) {
 	const results = [];
-	const chunks = args.trim().split(/\s*,\s*/g);
+	const chunks = arguments_.trim().split(/\s*,\s*/g);
 	let matches;
 
 	for (const chunk of chunks) {
-		if (!isNaN(chunk)) {
-			results.push(Number(chunk));
+		const number = Number(chunk);
+		if (!Number.isNaN(number)) {
+			results.push(number);
 		} else if ((matches = chunk.match(STRING_REGEX))) {
-			results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, chr) => escape ? unescape(escape) : chr));
+			results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character));
 		} else {
 			throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
 		}
@@ -73,36 +81,34 @@ function buildStyle(chalk, styles) {
 	}
 
 	let current = chalk;
-	for (const styleName of Object.keys(enabled)) {
-		if (Array.isArray(enabled[styleName])) {
-			if (!(styleName in current)) {
-				throw new Error(`Unknown Chalk style: ${styleName}`);
-			}
+	for (const [styleName, styles] of Object.entries(enabled)) {
+		if (!Array.isArray(styles)) {
+			continue;
+		}
 
-			if (enabled[styleName].length > 0) {
-				current = current[styleName].apply(current, enabled[styleName]);
-			} else {
-				current = current[styleName];
-			}
+		if (!(styleName in current)) {
+			throw new Error(`Unknown Chalk style: ${styleName}`);
 		}
+
+		current = styles.length > 0 ? current[styleName](...styles) : current[styleName];
 	}
 
 	return current;
 }
 
-module.exports = (chalk, tmp) => {
+module.exports = (chalk, temporary) => {
 	const styles = [];
 	const chunks = [];
 	let chunk = [];
 
 	// eslint-disable-next-line max-params
-	tmp.replace(TEMPLATE_REGEX, (m, escapeChar, inverse, style, close, chr) => {
-		if (escapeChar) {
-			chunk.push(unescape(escapeChar));
+	temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => {
+		if (escapeCharacter) {
+			chunk.push(unescape(escapeCharacter));
 		} else if (style) {
-			const str = chunk.join('');
+			const string = chunk.join('');
 			chunk = [];
-			chunks.push(styles.length === 0 ? str : buildStyle(chalk, styles)(str));
+			chunks.push(styles.length === 0 ? string : buildStyle(chalk, styles)(string));
 			styles.push({inverse, styles: parseStyle(style)});
 		} else if (close) {
 			if (styles.length === 0) {
@@ -113,15 +119,15 @@ module.exports = (chalk, tmp) => {
 			chunk = [];
 			styles.pop();
 		} else {
-			chunk.push(chr);
+			chunk.push(character);
 		}
 	});
 
 	chunks.push(chunk.join(''));
 
 	if (styles.length > 0) {
-		const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`;
-		throw new Error(errMsg);
+		const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`;
+		throw new Error(errMessage);
 	}
 
 	return chunks.join('');
diff --git a/node_modules/chalk/source/util.js b/node_modules/chalk/source/util.js
new file mode 100644
index 0000000000000000000000000000000000000000..ca466fd466c07f5b0be80ed7a99207813e8f765c
--- /dev/null
+++ b/node_modules/chalk/source/util.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const stringReplaceAll = (string, substring, replacer) => {
+	let index = string.indexOf(substring);
+	if (index === -1) {
+		return string;
+	}
+
+	const substringLength = substring.length;
+	let endIndex = 0;
+	let returnValue = '';
+	do {
+		returnValue += string.substr(endIndex, index - endIndex) + substring + replacer;
+		endIndex = index + substringLength;
+		index = string.indexOf(substring, endIndex);
+	} while (index !== -1);
+
+	returnValue += string.substr(endIndex);
+	return returnValue;
+};
+
+const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => {
+	let endIndex = 0;
+	let returnValue = '';
+	do {
+		const gotCR = string[index - 1] === '\r';
+		returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix;
+		endIndex = index + 1;
+		index = string.indexOf('\n', endIndex);
+	} while (index !== -1);
+
+	returnValue += string.substr(endIndex);
+	return returnValue;
+};
+
+module.exports = {
+	stringReplaceAll,
+	stringEncaseCRLFWithFirstIndex
+};
diff --git a/node_modules/chalk/types/index.d.ts b/node_modules/chalk/types/index.d.ts
deleted file mode 100644
index b4e4dc57ed01b7056e20db5a8e3d23ee6014a343..0000000000000000000000000000000000000000
--- a/node_modules/chalk/types/index.d.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-// Type definitions for Chalk
-// Definitions by: Thomas Sauer <https://github.com/t-sauer>
-
-export const enum Level {
-	None = 0,
-	Basic = 1,
-	Ansi256 = 2,
-	TrueColor = 3
-}
-
-export interface ChalkOptions {
-	enabled?: boolean;
-	level?: Level;
-}
-
-export interface ChalkConstructor {
-	new (options?: ChalkOptions): Chalk;
-	(options?: ChalkOptions): Chalk;
-}
-
-export interface ColorSupport {
-	level: Level;
-	hasBasic: boolean;
-	has256: boolean;
-	has16m: boolean;
-}
-
-export interface Chalk {
-	(...text: string[]): string;
-	(text: TemplateStringsArray, ...placeholders: string[]): string;
-	constructor: ChalkConstructor;
-	enabled: boolean;
-	level: Level;
-	rgb(r: number, g: number, b: number): this;
-	hsl(h: number, s: number, l: number): this;
-	hsv(h: number, s: number, v: number): this;
-	hwb(h: number, w: number, b: number): this;
-	bgHex(color: string): this;
-	bgKeyword(color: string): this;
-	bgRgb(r: number, g: number, b: number): this;
-	bgHsl(h: number, s: number, l: number): this;
-	bgHsv(h: number, s: number, v: number): this;
-	bgHwb(h: number, w: number, b: number): this;
-	hex(color: string): this;
-	keyword(color: string): this;
-
-	readonly reset: this;
-	readonly bold: this;
-	readonly dim: this;
-	readonly italic: this;
-	readonly underline: this;
-	readonly inverse: this;
-	readonly hidden: this;
-	readonly strikethrough: this;
-
-	readonly visible: this;
-
-	readonly black: this;
-	readonly red: this;
-	readonly green: this;
-	readonly yellow: this;
-	readonly blue: this;
-	readonly magenta: this;
-	readonly cyan: this;
-	readonly white: this;
-	readonly gray: this;
-	readonly grey: this;
-	readonly blackBright: this;
-	readonly redBright: this;
-	readonly greenBright: this;
-	readonly yellowBright: this;
-	readonly blueBright: this;
-	readonly magentaBright: this;
-	readonly cyanBright: this;
-	readonly whiteBright: this;
-
-	readonly bgBlack: this;
-	readonly bgRed: this;
-	readonly bgGreen: this;
-	readonly bgYellow: this;
-	readonly bgBlue: this;
-	readonly bgMagenta: this;
-	readonly bgCyan: this;
-	readonly bgWhite: this;
-	readonly bgBlackBright: this;
-	readonly bgRedBright: this;
-	readonly bgGreenBright: this;
-	readonly bgYellowBright: this;
-	readonly bgBlueBright: this;
-	readonly bgMagentaBright: this;
-	readonly bgCyanBright: this;
-	readonly bgWhiteBright: this;
-}
-
-declare const chalk: Chalk & { supportsColor: ColorSupport };
-
-export default chalk
diff --git a/node_modules/color-convert/conversions.js b/node_modules/color-convert/conversions.js
index 32172007ec0b17209337204b4bf73c0fe6812e27..2657f265c9e1022ed06a232f4da4db578d3d3fb0 100644
--- a/node_modules/color-convert/conversions.js
+++ b/node_modules/color-convert/conversions.js
@@ -1,18 +1,17 @@
 /* MIT license */
-var cssKeywords = require('color-name');
+/* eslint-disable no-mixed-operators */
+const cssKeywords = require('color-name');
 
 // NOTE: conversions should only return primitive values (i.e. arrays, or
 //       values that give correct `typeof` results).
 //       do not use box values types (i.e. Number(), String(), etc.)
 
-var reverseKeywords = {};
-for (var key in cssKeywords) {
-	if (cssKeywords.hasOwnProperty(key)) {
-		reverseKeywords[cssKeywords[key]] = key;
-	}
+const reverseKeywords = {};
+for (const key of Object.keys(cssKeywords)) {
+	reverseKeywords[cssKeywords[key]] = key;
 }
 
-var convert = module.exports = {
+const convert = {
 	rgb: {channels: 3, labels: 'rgb'},
 	hsl: {channels: 3, labels: 'hsl'},
 	hsv: {channels: 3, labels: 'hsv'},
@@ -30,40 +29,38 @@ var convert = module.exports = {
 	gray: {channels: 1, labels: ['gray']}
 };
 
-// hide .channels and .labels properties
-for (var model in convert) {
-	if (convert.hasOwnProperty(model)) {
-		if (!('channels' in convert[model])) {
-			throw new Error('missing channels property: ' + model);
-		}
+module.exports = convert;
 
-		if (!('labels' in convert[model])) {
-			throw new Error('missing channel labels property: ' + model);
-		}
+// Hide .channels and .labels properties
+for (const model of Object.keys(convert)) {
+	if (!('channels' in convert[model])) {
+		throw new Error('missing channels property: ' + model);
+	}
 
-		if (convert[model].labels.length !== convert[model].channels) {
-			throw new Error('channel and label counts mismatch: ' + model);
-		}
+	if (!('labels' in convert[model])) {
+		throw new Error('missing channel labels property: ' + model);
+	}
 
-		var channels = convert[model].channels;
-		var labels = convert[model].labels;
-		delete convert[model].channels;
-		delete convert[model].labels;
-		Object.defineProperty(convert[model], 'channels', {value: channels});
-		Object.defineProperty(convert[model], 'labels', {value: labels});
+	if (convert[model].labels.length !== convert[model].channels) {
+		throw new Error('channel and label counts mismatch: ' + model);
 	}
+
+	const {channels, labels} = convert[model];
+	delete convert[model].channels;
+	delete convert[model].labels;
+	Object.defineProperty(convert[model], 'channels', {value: channels});
+	Object.defineProperty(convert[model], 'labels', {value: labels});
 }
 
 convert.rgb.hsl = function (rgb) {
-	var r = rgb[0] / 255;
-	var g = rgb[1] / 255;
-	var b = rgb[2] / 255;
-	var min = Math.min(r, g, b);
-	var max = Math.max(r, g, b);
-	var delta = max - min;
-	var h;
-	var s;
-	var l;
+	const r = rgb[0] / 255;
+	const g = rgb[1] / 255;
+	const b = rgb[2] / 255;
+	const min = Math.min(r, g, b);
+	const max = Math.max(r, g, b);
+	const delta = max - min;
+	let h;
+	let s;
 
 	if (max === min) {
 		h = 0;
@@ -81,7 +78,7 @@ convert.rgb.hsl = function (rgb) {
 		h += 360;
 	}
 
-	l = (min + max) / 2;
+	const l = (min + max) / 2;
 
 	if (max === min) {
 		s = 0;
@@ -95,23 +92,24 @@ convert.rgb.hsl = function (rgb) {
 };
 
 convert.rgb.hsv = function (rgb) {
-	var rdif;
-	var gdif;
-	var bdif;
-	var h;
-	var s;
-
-	var r = rgb[0] / 255;
-	var g = rgb[1] / 255;
-	var b = rgb[2] / 255;
-	var v = Math.max(r, g, b);
-	var diff = v - Math.min(r, g, b);
-	var diffc = function (c) {
+	let rdif;
+	let gdif;
+	let bdif;
+	let h;
+	let s;
+
+	const r = rgb[0] / 255;
+	const g = rgb[1] / 255;
+	const b = rgb[2] / 255;
+	const v = Math.max(r, g, b);
+	const diff = v - Math.min(r, g, b);
+	const diffc = function (c) {
 		return (v - c) / 6 / diff + 1 / 2;
 	};
 
 	if (diff === 0) {
-		h = s = 0;
+		h = 0;
+		s = 0;
 	} else {
 		s = diff / v;
 		rdif = diffc(r);
@@ -125,6 +123,7 @@ convert.rgb.hsv = function (rgb) {
 		} else if (b === v) {
 			h = (2 / 3) + gdif - rdif;
 		}
+
 		if (h < 0) {
 			h += 1;
 		} else if (h > 1) {
@@ -140,11 +139,11 @@ convert.rgb.hsv = function (rgb) {
 };
 
 convert.rgb.hwb = function (rgb) {
-	var r = rgb[0];
-	var g = rgb[1];
-	var b = rgb[2];
-	var h = convert.rgb.hsl(rgb)[0];
-	var w = 1 / 255 * Math.min(r, Math.min(g, b));
+	const r = rgb[0];
+	const g = rgb[1];
+	let b = rgb[2];
+	const h = convert.rgb.hsl(rgb)[0];
+	const w = 1 / 255 * Math.min(r, Math.min(g, b));
 
 	b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
 
@@ -152,54 +151,48 @@ convert.rgb.hwb = function (rgb) {
 };
 
 convert.rgb.cmyk = function (rgb) {
-	var r = rgb[0] / 255;
-	var g = rgb[1] / 255;
-	var b = rgb[2] / 255;
-	var c;
-	var m;
-	var y;
-	var k;
-
-	k = Math.min(1 - r, 1 - g, 1 - b);
-	c = (1 - r - k) / (1 - k) || 0;
-	m = (1 - g - k) / (1 - k) || 0;
-	y = (1 - b - k) / (1 - k) || 0;
+	const r = rgb[0] / 255;
+	const g = rgb[1] / 255;
+	const b = rgb[2] / 255;
+
+	const k = Math.min(1 - r, 1 - g, 1 - b);
+	const c = (1 - r - k) / (1 - k) || 0;
+	const m = (1 - g - k) / (1 - k) || 0;
+	const y = (1 - b - k) / (1 - k) || 0;
 
 	return [c * 100, m * 100, y * 100, k * 100];
 };
 
-/**
- * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
- * */
 function comparativeDistance(x, y) {
+	/*
+		See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
+	*/
 	return (
-		Math.pow(x[0] - y[0], 2) +
-		Math.pow(x[1] - y[1], 2) +
-		Math.pow(x[2] - y[2], 2)
+		((x[0] - y[0]) ** 2) +
+		((x[1] - y[1]) ** 2) +
+		((x[2] - y[2]) ** 2)
 	);
 }
 
 convert.rgb.keyword = function (rgb) {
-	var reversed = reverseKeywords[rgb];
+	const reversed = reverseKeywords[rgb];
 	if (reversed) {
 		return reversed;
 	}
 
-	var currentClosestDistance = Infinity;
-	var currentClosestKeyword;
+	let currentClosestDistance = Infinity;
+	let currentClosestKeyword;
 
-	for (var keyword in cssKeywords) {
-		if (cssKeywords.hasOwnProperty(keyword)) {
-			var value = cssKeywords[keyword];
+	for (const keyword of Object.keys(cssKeywords)) {
+		const value = cssKeywords[keyword];
 
-			// Compute comparative distance
-			var distance = comparativeDistance(rgb, value);
+		// Compute comparative distance
+		const distance = comparativeDistance(rgb, value);
 
-			// Check if its less, if so set as closest
-			if (distance < currentClosestDistance) {
-				currentClosestDistance = distance;
-				currentClosestKeyword = keyword;
-			}
+		// Check if its less, if so set as closest
+		if (distance < currentClosestDistance) {
+			currentClosestDistance = distance;
+			currentClosestKeyword = keyword;
 		}
 	}
 
@@ -211,55 +204,50 @@ convert.keyword.rgb = function (keyword) {
 };
 
 convert.rgb.xyz = function (rgb) {
-	var r = rgb[0] / 255;
-	var g = rgb[1] / 255;
-	var b = rgb[2] / 255;
+	let r = rgb[0] / 255;
+	let g = rgb[1] / 255;
+	let b = rgb[2] / 255;
 
-	// assume sRGB
-	r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92);
-	g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92);
-	b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92);
+	// Assume sRGB
+	r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92);
+	g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92);
+	b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92);
 
-	var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
-	var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
-	var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
+	const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
+	const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
+	const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
 
 	return [x * 100, y * 100, z * 100];
 };
 
 convert.rgb.lab = function (rgb) {
-	var xyz = convert.rgb.xyz(rgb);
-	var x = xyz[0];
-	var y = xyz[1];
-	var z = xyz[2];
-	var l;
-	var a;
-	var b;
+	const xyz = convert.rgb.xyz(rgb);
+	let x = xyz[0];
+	let y = xyz[1];
+	let z = xyz[2];
 
 	x /= 95.047;
 	y /= 100;
 	z /= 108.883;
 
-	x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116);
-	y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116);
-	z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116);
+	x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
+	y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
+	z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
 
-	l = (116 * y) - 16;
-	a = 500 * (x - y);
-	b = 200 * (y - z);
+	const l = (116 * y) - 16;
+	const a = 500 * (x - y);
+	const b = 200 * (y - z);
 
 	return [l, a, b];
 };
 
 convert.hsl.rgb = function (hsl) {
-	var h = hsl[0] / 360;
-	var s = hsl[1] / 100;
-	var l = hsl[2] / 100;
-	var t1;
-	var t2;
-	var t3;
-	var rgb;
-	var val;
+	const h = hsl[0] / 360;
+	const s = hsl[1] / 100;
+	const l = hsl[2] / 100;
+	let t2;
+	let t3;
+	let val;
 
 	if (s === 0) {
 		val = l * 255;
@@ -272,14 +260,15 @@ convert.hsl.rgb = function (hsl) {
 		t2 = l + s - l * s;
 	}
 
-	t1 = 2 * l - t2;
+	const t1 = 2 * l - t2;
 
-	rgb = [0, 0, 0];
-	for (var i = 0; i < 3; i++) {
+	const rgb = [0, 0, 0];
+	for (let i = 0; i < 3; i++) {
 		t3 = h + 1 / 3 * -(i - 1);
 		if (t3 < 0) {
 			t3++;
 		}
+
 		if (t3 > 1) {
 			t3--;
 		}
@@ -301,33 +290,31 @@ convert.hsl.rgb = function (hsl) {
 };
 
 convert.hsl.hsv = function (hsl) {
-	var h = hsl[0];
-	var s = hsl[1] / 100;
-	var l = hsl[2] / 100;
-	var smin = s;
-	var lmin = Math.max(l, 0.01);
-	var sv;
-	var v;
+	const h = hsl[0];
+	let s = hsl[1] / 100;
+	let l = hsl[2] / 100;
+	let smin = s;
+	const lmin = Math.max(l, 0.01);
 
 	l *= 2;
 	s *= (l <= 1) ? l : 2 - l;
 	smin *= lmin <= 1 ? lmin : 2 - lmin;
-	v = (l + s) / 2;
-	sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
+	const v = (l + s) / 2;
+	const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
 
 	return [h, sv * 100, v * 100];
 };
 
 convert.hsv.rgb = function (hsv) {
-	var h = hsv[0] / 60;
-	var s = hsv[1] / 100;
-	var v = hsv[2] / 100;
-	var hi = Math.floor(h) % 6;
-
-	var f = h - Math.floor(h);
-	var p = 255 * v * (1 - s);
-	var q = 255 * v * (1 - (s * f));
-	var t = 255 * v * (1 - (s * (1 - f)));
+	const h = hsv[0] / 60;
+	const s = hsv[1] / 100;
+	let v = hsv[2] / 100;
+	const hi = Math.floor(h) % 6;
+
+	const f = h - Math.floor(h);
+	const p = 255 * v * (1 - s);
+	const q = 255 * v * (1 - (s * f));
+	const t = 255 * v * (1 - (s * (1 - f)));
 	v *= 255;
 
 	switch (hi) {
@@ -347,16 +334,15 @@ convert.hsv.rgb = function (hsv) {
 };
 
 convert.hsv.hsl = function (hsv) {
-	var h = hsv[0];
-	var s = hsv[1] / 100;
-	var v = hsv[2] / 100;
-	var vmin = Math.max(v, 0.01);
-	var lmin;
-	var sl;
-	var l;
+	const h = hsv[0];
+	const s = hsv[1] / 100;
+	const v = hsv[2] / 100;
+	const vmin = Math.max(v, 0.01);
+	let sl;
+	let l;
 
 	l = (2 - s) * v;
-	lmin = (2 - s) * vmin;
+	const lmin = (2 - s) * vmin;
 	sl = s * vmin;
 	sl /= (lmin <= 1) ? lmin : 2 - lmin;
 	sl = sl || 0;
@@ -367,87 +353,83 @@ convert.hsv.hsl = function (hsv) {
 
 // http://dev.w3.org/csswg/css-color/#hwb-to-rgb
 convert.hwb.rgb = function (hwb) {
-	var h = hwb[0] / 360;
-	var wh = hwb[1] / 100;
-	var bl = hwb[2] / 100;
-	var ratio = wh + bl;
-	var i;
-	var v;
-	var f;
-	var n;
-
-	// wh + bl cant be > 1
+	const h = hwb[0] / 360;
+	let wh = hwb[1] / 100;
+	let bl = hwb[2] / 100;
+	const ratio = wh + bl;
+	let f;
+
+	// Wh + bl cant be > 1
 	if (ratio > 1) {
 		wh /= ratio;
 		bl /= ratio;
 	}
 
-	i = Math.floor(6 * h);
-	v = 1 - bl;
+	const i = Math.floor(6 * h);
+	const v = 1 - bl;
 	f = 6 * h - i;
 
 	if ((i & 0x01) !== 0) {
 		f = 1 - f;
 	}
 
-	n = wh + f * (v - wh); // linear interpolation
+	const n = wh + f * (v - wh); // Linear interpolation
 
-	var r;
-	var g;
-	var b;
+	let r;
+	let g;
+	let b;
+	/* eslint-disable max-statements-per-line,no-multi-spaces */
 	switch (i) {
 		default:
 		case 6:
-		case 0: r = v; g = n; b = wh; break;
-		case 1: r = n; g = v; b = wh; break;
-		case 2: r = wh; g = v; b = n; break;
-		case 3: r = wh; g = n; b = v; break;
-		case 4: r = n; g = wh; b = v; break;
-		case 5: r = v; g = wh; b = n; break;
+		case 0: r = v;  g = n;  b = wh; break;
+		case 1: r = n;  g = v;  b = wh; break;
+		case 2: r = wh; g = v;  b = n; break;
+		case 3: r = wh; g = n;  b = v; break;
+		case 4: r = n;  g = wh; b = v; break;
+		case 5: r = v;  g = wh; b = n; break;
 	}
+	/* eslint-enable max-statements-per-line,no-multi-spaces */
 
 	return [r * 255, g * 255, b * 255];
 };
 
 convert.cmyk.rgb = function (cmyk) {
-	var c = cmyk[0] / 100;
-	var m = cmyk[1] / 100;
-	var y = cmyk[2] / 100;
-	var k = cmyk[3] / 100;
-	var r;
-	var g;
-	var b;
-
-	r = 1 - Math.min(1, c * (1 - k) + k);
-	g = 1 - Math.min(1, m * (1 - k) + k);
-	b = 1 - Math.min(1, y * (1 - k) + k);
+	const c = cmyk[0] / 100;
+	const m = cmyk[1] / 100;
+	const y = cmyk[2] / 100;
+	const k = cmyk[3] / 100;
+
+	const r = 1 - Math.min(1, c * (1 - k) + k);
+	const g = 1 - Math.min(1, m * (1 - k) + k);
+	const b = 1 - Math.min(1, y * (1 - k) + k);
 
 	return [r * 255, g * 255, b * 255];
 };
 
 convert.xyz.rgb = function (xyz) {
-	var x = xyz[0] / 100;
-	var y = xyz[1] / 100;
-	var z = xyz[2] / 100;
-	var r;
-	var g;
-	var b;
+	const x = xyz[0] / 100;
+	const y = xyz[1] / 100;
+	const z = xyz[2] / 100;
+	let r;
+	let g;
+	let b;
 
 	r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
 	g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
 	b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
 
-	// assume sRGB
+	// Assume sRGB
 	r = r > 0.0031308
-		? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055)
+		? ((1.055 * (r ** (1.0 / 2.4))) - 0.055)
 		: r * 12.92;
 
 	g = g > 0.0031308
-		? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055)
+		? ((1.055 * (g ** (1.0 / 2.4))) - 0.055)
 		: g * 12.92;
 
 	b = b > 0.0031308
-		? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055)
+		? ((1.055 * (b ** (1.0 / 2.4))) - 0.055)
 		: b * 12.92;
 
 	r = Math.min(Math.max(0, r), 1);
@@ -458,43 +440,40 @@ convert.xyz.rgb = function (xyz) {
 };
 
 convert.xyz.lab = function (xyz) {
-	var x = xyz[0];
-	var y = xyz[1];
-	var z = xyz[2];
-	var l;
-	var a;
-	var b;
+	let x = xyz[0];
+	let y = xyz[1];
+	let z = xyz[2];
 
 	x /= 95.047;
 	y /= 100;
 	z /= 108.883;
 
-	x = x > 0.008856 ? Math.pow(x, 1 / 3) : (7.787 * x) + (16 / 116);
-	y = y > 0.008856 ? Math.pow(y, 1 / 3) : (7.787 * y) + (16 / 116);
-	z = z > 0.008856 ? Math.pow(z, 1 / 3) : (7.787 * z) + (16 / 116);
+	x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
+	y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
+	z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
 
-	l = (116 * y) - 16;
-	a = 500 * (x - y);
-	b = 200 * (y - z);
+	const l = (116 * y) - 16;
+	const a = 500 * (x - y);
+	const b = 200 * (y - z);
 
 	return [l, a, b];
 };
 
 convert.lab.xyz = function (lab) {
-	var l = lab[0];
-	var a = lab[1];
-	var b = lab[2];
-	var x;
-	var y;
-	var z;
+	const l = lab[0];
+	const a = lab[1];
+	const b = lab[2];
+	let x;
+	let y;
+	let z;
 
 	y = (l + 16) / 116;
 	x = a / 500 + y;
 	z = y - b / 200;
 
-	var y2 = Math.pow(y, 3);
-	var x2 = Math.pow(x, 3);
-	var z2 = Math.pow(z, 3);
+	const y2 = y ** 3;
+	const x2 = x ** 3;
+	const z2 = z ** 3;
 	y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
 	x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
 	z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;
@@ -507,45 +486,38 @@ convert.lab.xyz = function (lab) {
 };
 
 convert.lab.lch = function (lab) {
-	var l = lab[0];
-	var a = lab[1];
-	var b = lab[2];
-	var hr;
-	var h;
-	var c;
-
-	hr = Math.atan2(b, a);
+	const l = lab[0];
+	const a = lab[1];
+	const b = lab[2];
+	let h;
+
+	const hr = Math.atan2(b, a);
 	h = hr * 360 / 2 / Math.PI;
 
 	if (h < 0) {
 		h += 360;
 	}
 
-	c = Math.sqrt(a * a + b * b);
+	const c = Math.sqrt(a * a + b * b);
 
 	return [l, c, h];
 };
 
 convert.lch.lab = function (lch) {
-	var l = lch[0];
-	var c = lch[1];
-	var h = lch[2];
-	var a;
-	var b;
-	var hr;
+	const l = lch[0];
+	const c = lch[1];
+	const h = lch[2];
 
-	hr = h / 360 * 2 * Math.PI;
-	a = c * Math.cos(hr);
-	b = c * Math.sin(hr);
+	const hr = h / 360 * 2 * Math.PI;
+	const a = c * Math.cos(hr);
+	const b = c * Math.sin(hr);
 
 	return [l, a, b];
 };
 
-convert.rgb.ansi16 = function (args) {
-	var r = args[0];
-	var g = args[1];
-	var b = args[2];
-	var value = 1 in arguments ? arguments[1] : convert.rgb.hsv(args)[2]; // hsv -> ansi16 optimization
+convert.rgb.ansi16 = function (args, saturation = null) {
+	const [r, g, b] = args;
+	let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization
 
 	value = Math.round(value / 50);
 
@@ -553,7 +525,7 @@ convert.rgb.ansi16 = function (args) {
 		return 30;
 	}
 
-	var ansi = 30
+	let ansi = 30
 		+ ((Math.round(b / 255) << 2)
 		| (Math.round(g / 255) << 1)
 		| Math.round(r / 255));
@@ -566,17 +538,17 @@ convert.rgb.ansi16 = function (args) {
 };
 
 convert.hsv.ansi16 = function (args) {
-	// optimization here; we already know the value and don't need to get
+	// Optimization here; we already know the value and don't need to get
 	// it converted for us.
 	return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
 };
 
 convert.rgb.ansi256 = function (args) {
-	var r = args[0];
-	var g = args[1];
-	var b = args[2];
+	const r = args[0];
+	const g = args[1];
+	const b = args[2];
 
-	// we use the extended greyscale palette here, with the exception of
+	// We use the extended greyscale palette here, with the exception of
 	// black and white. normal palette only has 4 greyscale shades.
 	if (r === g && g === b) {
 		if (r < 8) {
@@ -590,7 +562,7 @@ convert.rgb.ansi256 = function (args) {
 		return Math.round(((r - 8) / 247) * 24) + 232;
 	}
 
-	var ansi = 16
+	const ansi = 16
 		+ (36 * Math.round(r / 255 * 5))
 		+ (6 * Math.round(g / 255 * 5))
 		+ Math.round(b / 255 * 5);
@@ -599,9 +571,9 @@ convert.rgb.ansi256 = function (args) {
 };
 
 convert.ansi16.rgb = function (args) {
-	var color = args % 10;
+	let color = args % 10;
 
-	// handle greyscale
+	// Handle greyscale
 	if (color === 0 || color === 7) {
 		if (args > 50) {
 			color += 3.5;
@@ -612,71 +584,71 @@ convert.ansi16.rgb = function (args) {
 		return [color, color, color];
 	}
 
-	var mult = (~~(args > 50) + 1) * 0.5;
-	var r = ((color & 1) * mult) * 255;
-	var g = (((color >> 1) & 1) * mult) * 255;
-	var b = (((color >> 2) & 1) * mult) * 255;
+	const mult = (~~(args > 50) + 1) * 0.5;
+	const r = ((color & 1) * mult) * 255;
+	const g = (((color >> 1) & 1) * mult) * 255;
+	const b = (((color >> 2) & 1) * mult) * 255;
 
 	return [r, g, b];
 };
 
 convert.ansi256.rgb = function (args) {
-	// handle greyscale
+	// Handle greyscale
 	if (args >= 232) {
-		var c = (args - 232) * 10 + 8;
+		const c = (args - 232) * 10 + 8;
 		return [c, c, c];
 	}
 
 	args -= 16;
 
-	var rem;
-	var r = Math.floor(args / 36) / 5 * 255;
-	var g = Math.floor((rem = args % 36) / 6) / 5 * 255;
-	var b = (rem % 6) / 5 * 255;
+	let rem;
+	const r = Math.floor(args / 36) / 5 * 255;
+	const g = Math.floor((rem = args % 36) / 6) / 5 * 255;
+	const b = (rem % 6) / 5 * 255;
 
 	return [r, g, b];
 };
 
 convert.rgb.hex = function (args) {
-	var integer = ((Math.round(args[0]) & 0xFF) << 16)
+	const integer = ((Math.round(args[0]) & 0xFF) << 16)
 		+ ((Math.round(args[1]) & 0xFF) << 8)
 		+ (Math.round(args[2]) & 0xFF);
 
-	var string = integer.toString(16).toUpperCase();
+	const string = integer.toString(16).toUpperCase();
 	return '000000'.substring(string.length) + string;
 };
 
 convert.hex.rgb = function (args) {
-	var match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
+	const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
 	if (!match) {
 		return [0, 0, 0];
 	}
 
-	var colorString = match[0];
+	let colorString = match[0];
 
 	if (match[0].length === 3) {
-		colorString = colorString.split('').map(function (char) {
+		colorString = colorString.split('').map(char => {
 			return char + char;
 		}).join('');
 	}
 
-	var integer = parseInt(colorString, 16);
-	var r = (integer >> 16) & 0xFF;
-	var g = (integer >> 8) & 0xFF;
-	var b = integer & 0xFF;
+	const integer = parseInt(colorString, 16);
+	const r = (integer >> 16) & 0xFF;
+	const g = (integer >> 8) & 0xFF;
+	const b = integer & 0xFF;
 
 	return [r, g, b];
 };
 
 convert.rgb.hcg = function (rgb) {
-	var r = rgb[0] / 255;
-	var g = rgb[1] / 255;
-	var b = rgb[2] / 255;
-	var max = Math.max(Math.max(r, g), b);
-	var min = Math.min(Math.min(r, g), b);
-	var chroma = (max - min);
-	var grayscale;
-	var hue;
+	const r = rgb[0] / 255;
+	const g = rgb[1] / 255;
+	const b = rgb[2] / 255;
+	const max = Math.max(Math.max(r, g), b);
+	const min = Math.min(Math.min(r, g), b);
+	const chroma = (max - min);
+	let grayscale;
+	let hue;
 
 	if (chroma < 1) {
 		grayscale = min / (1 - chroma);
@@ -693,7 +665,7 @@ convert.rgb.hcg = function (rgb) {
 	if (max === g) {
 		hue = 2 + (b - r) / chroma;
 	} else {
-		hue = 4 + (r - g) / chroma + 4;
+		hue = 4 + (r - g) / chroma;
 	}
 
 	hue /= 6;
@@ -703,17 +675,12 @@ convert.rgb.hcg = function (rgb) {
 };
 
 convert.hsl.hcg = function (hsl) {
-	var s = hsl[1] / 100;
-	var l = hsl[2] / 100;
-	var c = 1;
-	var f = 0;
+	const s = hsl[1] / 100;
+	const l = hsl[2] / 100;
 
-	if (l < 0.5) {
-		c = 2.0 * s * l;
-	} else {
-		c = 2.0 * s * (1.0 - l);
-	}
+	const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l));
 
+	let f = 0;
 	if (c < 1.0) {
 		f = (l - 0.5 * c) / (1.0 - c);
 	}
@@ -722,11 +689,11 @@ convert.hsl.hcg = function (hsl) {
 };
 
 convert.hsv.hcg = function (hsv) {
-	var s = hsv[1] / 100;
-	var v = hsv[2] / 100;
+	const s = hsv[1] / 100;
+	const v = hsv[2] / 100;
 
-	var c = s * v;
-	var f = 0;
+	const c = s * v;
+	let f = 0;
 
 	if (c < 1.0) {
 		f = (v - c) / (1 - c);
@@ -736,20 +703,21 @@ convert.hsv.hcg = function (hsv) {
 };
 
 convert.hcg.rgb = function (hcg) {
-	var h = hcg[0] / 360;
-	var c = hcg[1] / 100;
-	var g = hcg[2] / 100;
+	const h = hcg[0] / 360;
+	const c = hcg[1] / 100;
+	const g = hcg[2] / 100;
 
 	if (c === 0.0) {
 		return [g * 255, g * 255, g * 255];
 	}
 
-	var pure = [0, 0, 0];
-	var hi = (h % 1) * 6;
-	var v = hi % 1;
-	var w = 1 - v;
-	var mg = 0;
+	const pure = [0, 0, 0];
+	const hi = (h % 1) * 6;
+	const v = hi % 1;
+	const w = 1 - v;
+	let mg = 0;
 
+	/* eslint-disable max-statements-per-line */
 	switch (Math.floor(hi)) {
 		case 0:
 			pure[0] = 1; pure[1] = v; pure[2] = 0; break;
@@ -764,6 +732,7 @@ convert.hcg.rgb = function (hcg) {
 		default:
 			pure[0] = 1; pure[1] = 0; pure[2] = w;
 	}
+	/* eslint-enable max-statements-per-line */
 
 	mg = (1.0 - c) * g;
 
@@ -775,11 +744,11 @@ convert.hcg.rgb = function (hcg) {
 };
 
 convert.hcg.hsv = function (hcg) {
-	var c = hcg[1] / 100;
-	var g = hcg[2] / 100;
+	const c = hcg[1] / 100;
+	const g = hcg[2] / 100;
 
-	var v = c + g * (1.0 - c);
-	var f = 0;
+	const v = c + g * (1.0 - c);
+	let f = 0;
 
 	if (v > 0.0) {
 		f = c / v;
@@ -789,11 +758,11 @@ convert.hcg.hsv = function (hcg) {
 };
 
 convert.hcg.hsl = function (hcg) {
-	var c = hcg[1] / 100;
-	var g = hcg[2] / 100;
+	const c = hcg[1] / 100;
+	const g = hcg[2] / 100;
 
-	var l = g * (1.0 - c) + 0.5 * c;
-	var s = 0;
+	const l = g * (1.0 - c) + 0.5 * c;
+	let s = 0;
 
 	if (l > 0.0 && l < 0.5) {
 		s = c / (2 * l);
@@ -806,18 +775,18 @@ convert.hcg.hsl = function (hcg) {
 };
 
 convert.hcg.hwb = function (hcg) {
-	var c = hcg[1] / 100;
-	var g = hcg[2] / 100;
-	var v = c + g * (1.0 - c);
+	const c = hcg[1] / 100;
+	const g = hcg[2] / 100;
+	const v = c + g * (1.0 - c);
 	return [hcg[0], (v - c) * 100, (1 - v) * 100];
 };
 
 convert.hwb.hcg = function (hwb) {
-	var w = hwb[1] / 100;
-	var b = hwb[2] / 100;
-	var v = 1 - b;
-	var c = v - w;
-	var g = 0;
+	const w = hwb[1] / 100;
+	const b = hwb[2] / 100;
+	const v = 1 - b;
+	const c = v - w;
+	let g = 0;
 
 	if (c < 1) {
 		g = (v - c) / (1 - c);
@@ -838,10 +807,12 @@ convert.gray.rgb = function (args) {
 	return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
 };
 
-convert.gray.hsl = convert.gray.hsv = function (args) {
+convert.gray.hsl = function (args) {
 	return [0, 0, args[0]];
 };
 
+convert.gray.hsv = convert.gray.hsl;
+
 convert.gray.hwb = function (gray) {
 	return [0, 100, gray[0]];
 };
@@ -855,14 +826,14 @@ convert.gray.lab = function (gray) {
 };
 
 convert.gray.hex = function (gray) {
-	var val = Math.round(gray[0] / 100 * 255) & 0xFF;
-	var integer = (val << 16) + (val << 8) + val;
+	const val = Math.round(gray[0] / 100 * 255) & 0xFF;
+	const integer = (val << 16) + (val << 8) + val;
 
-	var string = integer.toString(16).toUpperCase();
+	const string = integer.toString(16).toUpperCase();
 	return '000000'.substring(string.length) + string;
 };
 
 convert.rgb.gray = function (rgb) {
-	var val = (rgb[0] + rgb[1] + rgb[2]) / 3;
+	const val = (rgb[0] + rgb[1] + rgb[2]) / 3;
 	return [val / 255 * 100];
 };
diff --git a/node_modules/color-convert/index.js b/node_modules/color-convert/index.js
index e65b5d775da3530c9e53fad82f3f0a76d571480e..b648e5737be6168bff5137cb1a5a897e55ce193d 100644
--- a/node_modules/color-convert/index.js
+++ b/node_modules/color-convert/index.js
@@ -1,24 +1,25 @@
-var conversions = require('./conversions');
-var route = require('./route');
+const conversions = require('./conversions');
+const route = require('./route');
 
-var convert = {};
+const convert = {};
 
-var models = Object.keys(conversions);
+const models = Object.keys(conversions);
 
 function wrapRaw(fn) {
-	var wrappedFn = function (args) {
-		if (args === undefined || args === null) {
-			return args;
+	const wrappedFn = function (...args) {
+		const arg0 = args[0];
+		if (arg0 === undefined || arg0 === null) {
+			return arg0;
 		}
 
-		if (arguments.length > 1) {
-			args = Array.prototype.slice.call(arguments);
+		if (arg0.length > 1) {
+			args = arg0;
 		}
 
 		return fn(args);
 	};
 
-	// preserve .conversion property if there is one
+	// Preserve .conversion property if there is one
 	if ('conversion' in fn) {
 		wrappedFn.conversion = fn.conversion;
 	}
@@ -27,22 +28,24 @@ function wrapRaw(fn) {
 }
 
 function wrapRounded(fn) {
-	var wrappedFn = function (args) {
-		if (args === undefined || args === null) {
-			return args;
+	const wrappedFn = function (...args) {
+		const arg0 = args[0];
+
+		if (arg0 === undefined || arg0 === null) {
+			return arg0;
 		}
 
-		if (arguments.length > 1) {
-			args = Array.prototype.slice.call(arguments);
+		if (arg0.length > 1) {
+			args = arg0;
 		}
 
-		var result = fn(args);
+		const result = fn(args);
 
-		// we're assuming the result is an array here.
+		// We're assuming the result is an array here.
 		// see notice in conversions.js; don't use box types
 		// in conversion functions.
 		if (typeof result === 'object') {
-			for (var len = result.length, i = 0; i < len; i++) {
+			for (let len = result.length, i = 0; i < len; i++) {
 				result[i] = Math.round(result[i]);
 			}
 		}
@@ -50,7 +53,7 @@ function wrapRounded(fn) {
 		return result;
 	};
 
-	// preserve .conversion property if there is one
+	// Preserve .conversion property if there is one
 	if ('conversion' in fn) {
 		wrappedFn.conversion = fn.conversion;
 	}
@@ -58,17 +61,17 @@ function wrapRounded(fn) {
 	return wrappedFn;
 }
 
-models.forEach(function (fromModel) {
+models.forEach(fromModel => {
 	convert[fromModel] = {};
 
 	Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels});
 	Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels});
 
-	var routes = route(fromModel);
-	var routeModels = Object.keys(routes);
+	const routes = route(fromModel);
+	const routeModels = Object.keys(routes);
 
-	routeModels.forEach(function (toModel) {
-		var fn = routes[toModel];
+	routeModels.forEach(toModel => {
+		const fn = routes[toModel];
 
 		convert[fromModel][toModel] = wrapRounded(fn);
 		convert[fromModel][toModel].raw = wrapRaw(fn);
diff --git a/node_modules/color-convert/package.json b/node_modules/color-convert/package.json
index dfbc471407ff4ccbcaabf2e072aeb4470950af61..6e48000c7c98fd844af784fb2fdf7060f13ed0b1 100644
--- a/node_modules/color-convert/package.json
+++ b/node_modules/color-convert/package.json
@@ -1,7 +1,7 @@
 {
   "name": "color-convert",
   "description": "Plain color conversion functions",
-  "version": "1.9.3",
+  "version": "2.0.1",
   "author": "Heather Arthur <fayearthur@gmail.com>",
   "license": "MIT",
   "repository": "Qix-/color-convert",
@@ -9,6 +9,9 @@
     "pretest": "xo",
     "test": "node test/basic.js"
   },
+  "engines": {
+    "node": ">=7.0.0"
+  },
   "keywords": [
     "color",
     "colour",
@@ -26,7 +29,6 @@
   "files": [
     "index.js",
     "conversions.js",
-    "css-keywords.js",
     "route.js"
   ],
   "xo": {
@@ -37,10 +39,10 @@
     }
   },
   "devDependencies": {
-    "chalk": "1.1.1",
-    "xo": "0.11.2"
+    "chalk": "^2.4.2",
+    "xo": "^0.24.0"
   },
   "dependencies": {
-    "color-name": "1.1.3"
+    "color-name": "~1.1.4"
   }
 }
diff --git a/node_modules/color-convert/route.js b/node_modules/color-convert/route.js
index 0a1fdea689e2a708b6a00f7988b69c27746ee9c7..1a08521b5a001793a0a2c705d442a29949b1f051 100644
--- a/node_modules/color-convert/route.js
+++ b/node_modules/color-convert/route.js
@@ -1,7 +1,7 @@
-var conversions = require('./conversions');
+const conversions = require('./conversions');
 
 /*
-	this function routes a model to all other models.
+	This function routes a model to all other models.
 
 	all functions that are routed have a property `.conversion` attached
 	to the returned synthetic function. This property is an array
@@ -12,11 +12,11 @@ var conversions = require('./conversions');
 */
 
 function buildGraph() {
-	var graph = {};
+	const graph = {};
 	// https://jsperf.com/object-keys-vs-for-in-with-closure/3
-	var models = Object.keys(conversions);
+	const models = Object.keys(conversions);
 
-	for (var len = models.length, i = 0; i < len; i++) {
+	for (let len = models.length, i = 0; i < len; i++) {
 		graph[models[i]] = {
 			// http://jsperf.com/1-vs-infinity
 			// micro-opt, but this is simple.
@@ -30,18 +30,18 @@ function buildGraph() {
 
 // https://en.wikipedia.org/wiki/Breadth-first_search
 function deriveBFS(fromModel) {
-	var graph = buildGraph();
-	var queue = [fromModel]; // unshift -> queue -> pop
+	const graph = buildGraph();
+	const queue = [fromModel]; // Unshift -> queue -> pop
 
 	graph[fromModel].distance = 0;
 
 	while (queue.length) {
-		var current = queue.pop();
-		var adjacents = Object.keys(conversions[current]);
+		const current = queue.pop();
+		const adjacents = Object.keys(conversions[current]);
 
-		for (var len = adjacents.length, i = 0; i < len; i++) {
-			var adjacent = adjacents[i];
-			var node = graph[adjacent];
+		for (let len = adjacents.length, i = 0; i < len; i++) {
+			const adjacent = adjacents[i];
+			const node = graph[adjacent];
 
 			if (node.distance === -1) {
 				node.distance = graph[current].distance + 1;
@@ -61,10 +61,10 @@ function link(from, to) {
 }
 
 function wrapConversion(toModel, graph) {
-	var path = [graph[toModel].parent, toModel];
-	var fn = conversions[graph[toModel].parent][toModel];
+	const path = [graph[toModel].parent, toModel];
+	let fn = conversions[graph[toModel].parent][toModel];
 
-	var cur = graph[toModel].parent;
+	let cur = graph[toModel].parent;
 	while (graph[cur].parent) {
 		path.unshift(graph[cur].parent);
 		fn = link(conversions[graph[cur].parent][cur], fn);
@@ -76,16 +76,16 @@ function wrapConversion(toModel, graph) {
 }
 
 module.exports = function (fromModel) {
-	var graph = deriveBFS(fromModel);
-	var conversion = {};
+	const graph = deriveBFS(fromModel);
+	const conversion = {};
 
-	var models = Object.keys(graph);
-	for (var len = models.length, i = 0; i < len; i++) {
-		var toModel = models[i];
-		var node = graph[toModel];
+	const models = Object.keys(graph);
+	for (let len = models.length, i = 0; i < len; i++) {
+		const toModel = models[i];
+		const node = graph[toModel];
 
 		if (node.parent === null) {
-			// no possible conversion, or this node is the source model.
+			// No possible conversion, or this node is the source model.
 			continue;
 		}
 
diff --git a/node_modules/color-name/.eslintrc.json b/node_modules/color-name/.eslintrc.json
deleted file mode 100644
index c50c250446ee6d06a87a590ecbf3905696b0871d..0000000000000000000000000000000000000000
--- a/node_modules/color-name/.eslintrc.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
-    "env": {
-        "browser": true,
-        "node": true,
-        "commonjs": true,
-        "es6": true
-    },
-    "extends": "eslint:recommended",
-    "rules": {
-        "strict": 2,
-        "indent": 0,
-        "linebreak-style": 0,
-        "quotes": 0,
-        "semi": 0,
-        "no-cond-assign": 1,
-        "no-constant-condition": 1,
-        "no-duplicate-case": 1,
-        "no-empty": 1,
-        "no-ex-assign": 1,
-        "no-extra-boolean-cast": 1,
-        "no-extra-semi": 1,
-        "no-fallthrough": 1,
-        "no-func-assign": 1,
-        "no-global-assign": 1,
-        "no-implicit-globals": 2,
-        "no-inner-declarations": ["error", "functions"],
-        "no-irregular-whitespace": 2,
-        "no-loop-func": 1,
-        "no-multi-str": 1,
-        "no-mixed-spaces-and-tabs": 1,
-        "no-proto": 1,
-        "no-sequences": 1,
-        "no-throw-literal": 1,
-        "no-unmodified-loop-condition": 1,
-        "no-useless-call": 1,
-        "no-void": 1,
-        "no-with": 2,
-        "wrap-iife": 1,
-        "no-redeclare": 1,
-        "no-unused-vars": ["error", { "vars": "all", "args": "none" }],
-        "no-sparse-arrays": 1
-    }
-}
diff --git a/node_modules/color-name/.npmignore b/node_modules/color-name/.npmignore
deleted file mode 100644
index 3854c07dc6e56fb0f62b3bf210d7b62e95aac733..0000000000000000000000000000000000000000
--- a/node_modules/color-name/.npmignore
+++ /dev/null
@@ -1,107 +0,0 @@
-//this will affect all the git repos
-git config --global core.excludesfile ~/.gitignore
-
-
-//update files since .ignore won't if already tracked
-git rm --cached <file>
-
-# Compiled source #
-###################
-*.com
-*.class
-*.dll
-*.exe
-*.o
-*.so
-
-# Packages #
-############
-# it's better to unpack these files and commit the raw source
-# git has its own built in compression methods
-*.7z
-*.dmg
-*.gz
-*.iso
-*.jar
-*.rar
-*.tar
-*.zip
-
-# Logs and databases #
-######################
-*.log
-*.sql
-*.sqlite
-
-# OS generated files #
-######################
-.DS_Store
-.DS_Store?
-._*
-.Spotlight-V100
-.Trashes
-# Icon?
-ehthumbs.db
-Thumbs.db
-.cache
-.project
-.settings
-.tmproj
-*.esproj
-nbproject
-
-# Numerous always-ignore extensions #
-#####################################
-*.diff
-*.err
-*.orig
-*.rej
-*.swn
-*.swo
-*.swp
-*.vi
-*~
-*.sass-cache
-*.grunt
-*.tmp
-
-# Dreamweaver added files #
-###########################
-_notes
-dwsync.xml
-
-# Komodo #
-###########################
-*.komodoproject
-.komodotools
-
-# Node #
-#####################
-node_modules
-
-# Bower #
-#####################
-bower_components
-
-# Folders to ignore #
-#####################
-.hg
-.svn
-.CVS
-intermediate
-publish
-.idea
-.graphics
-_test
-_archive
-uploads
-tmp
-
-# Vim files to ignore #
-#######################
-.VimballRecord
-.netrwhist
-
-bundle.*
-
-_demo
\ No newline at end of file
diff --git a/node_modules/color-name/package.json b/node_modules/color-name/package.json
index d061123ef02f40a2c129c0bbd24f4459c0c4468f..7acc90285c96fbbe8b6f12ef32cd2384a72e6f62 100644
--- a/node_modules/color-name/package.json
+++ b/node_modules/color-name/package.json
@@ -1,14 +1,17 @@
 {
   "name": "color-name",
-  "version": "1.1.3",
+  "version": "1.1.4",
   "description": "A list of color names and its values",
   "main": "index.js",
+  "files": [
+    "index.js"
+  ],
   "scripts": {
     "test": "node test.js"
   },
   "repository": {
     "type": "git",
-    "url": "git@github.com:dfcreative/color-name.git"
+    "url": "git@github.com:colorjs/color-name.git"
   },
   "keywords": [
     "color-name",
@@ -19,7 +22,7 @@
   "author": "DY <dfcreative@gmail.com>",
   "license": "MIT",
   "bugs": {
-    "url": "https://github.com/dfcreative/color-name/issues"
+    "url": "https://github.com/colorjs/color-name/issues"
   },
-  "homepage": "https://github.com/dfcreative/color-name"
+  "homepage": "https://github.com/colorjs/color-name"
 }
diff --git a/node_modules/color-name/test.js b/node_modules/color-name/test.js
deleted file mode 100644
index 7a08746215ed3cd497b5592978772c47adc4a71f..0000000000000000000000000000000000000000
--- a/node_modules/color-name/test.js
+++ /dev/null
@@ -1,7 +0,0 @@
-'use strict'
-
-var names = require('./');
-var assert = require('assert');
-
-assert.deepEqual(names.red, [255,0,0]);
-assert.deepEqual(names.aliceblue, [240,248,255]);
diff --git a/node_modules/concat-stream/LICENSE b/node_modules/concat-stream/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..99c130e1de342703106a2032f2d8f8329fea1af4
--- /dev/null
+++ b/node_modules/concat-stream/LICENSE
@@ -0,0 +1,24 @@
+The MIT License
+
+Copyright (c) 2013 Max Ogden
+
+Permission is hereby granted, free of charge, 
+to any person obtaining a copy of this software and 
+associated documentation files (the "Software"), to 
+deal in the Software without restriction, including 
+without limitation the rights to use, copy, modify, 
+merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom 
+the Software is furnished to do so, 
+subject to the following conditions:
+
+The above copyright notice and this permission notice 
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/concat-stream/index.js b/node_modules/concat-stream/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..dd672a761b2f8212455353b05385b85573424567
--- /dev/null
+++ b/node_modules/concat-stream/index.js
@@ -0,0 +1,144 @@
+var Writable = require('readable-stream').Writable
+var inherits = require('inherits')
+var bufferFrom = require('buffer-from')
+
+if (typeof Uint8Array === 'undefined') {
+  var U8 = require('typedarray').Uint8Array
+} else {
+  var U8 = Uint8Array
+}
+
+function ConcatStream(opts, cb) {
+  if (!(this instanceof ConcatStream)) return new ConcatStream(opts, cb)
+
+  if (typeof opts === 'function') {
+    cb = opts
+    opts = {}
+  }
+  if (!opts) opts = {}
+
+  var encoding = opts.encoding
+  var shouldInferEncoding = false
+
+  if (!encoding) {
+    shouldInferEncoding = true
+  } else {
+    encoding =  String(encoding).toLowerCase()
+    if (encoding === 'u8' || encoding === 'uint8') {
+      encoding = 'uint8array'
+    }
+  }
+
+  Writable.call(this, { objectMode: true })
+
+  this.encoding = encoding
+  this.shouldInferEncoding = shouldInferEncoding
+
+  if (cb) this.on('finish', function () { cb(this.getBody()) })
+  this.body = []
+}
+
+module.exports = ConcatStream
+inherits(ConcatStream, Writable)
+
+ConcatStream.prototype._write = function(chunk, enc, next) {
+  this.body.push(chunk)
+  next()
+}
+
+ConcatStream.prototype.inferEncoding = function (buff) {
+  var firstBuffer = buff === undefined ? this.body[0] : buff;
+  if (Buffer.isBuffer(firstBuffer)) return 'buffer'
+  if (typeof Uint8Array !== 'undefined' && firstBuffer instanceof Uint8Array) return 'uint8array'
+  if (Array.isArray(firstBuffer)) return 'array'
+  if (typeof firstBuffer === 'string') return 'string'
+  if (Object.prototype.toString.call(firstBuffer) === "[object Object]") return 'object'
+  return 'buffer'
+}
+
+ConcatStream.prototype.getBody = function () {
+  if (!this.encoding && this.body.length === 0) return []
+  if (this.shouldInferEncoding) this.encoding = this.inferEncoding()
+  if (this.encoding === 'array') return arrayConcat(this.body)
+  if (this.encoding === 'string') return stringConcat(this.body)
+  if (this.encoding === 'buffer') return bufferConcat(this.body)
+  if (this.encoding === 'uint8array') return u8Concat(this.body)
+  return this.body
+}
+
+var isArray = Array.isArray || function (arr) {
+  return Object.prototype.toString.call(arr) == '[object Array]'
+}
+
+function isArrayish (arr) {
+  return /Array\]$/.test(Object.prototype.toString.call(arr))
+}
+
+function isBufferish (p) {
+  return typeof p === 'string' || isArrayish(p) || (p && typeof p.subarray === 'function')
+}
+
+function stringConcat (parts) {
+  var strings = []
+  var needsToString = false
+  for (var i = 0; i < parts.length; i++) {
+    var p = parts[i]
+    if (typeof p === 'string') {
+      strings.push(p)
+    } else if (Buffer.isBuffer(p)) {
+      strings.push(p)
+    } else if (isBufferish(p)) {
+      strings.push(bufferFrom(p))
+    } else {
+      strings.push(bufferFrom(String(p)))
+    }
+  }
+  if (Buffer.isBuffer(parts[0])) {
+    strings = Buffer.concat(strings)
+    strings = strings.toString('utf8')
+  } else {
+    strings = strings.join('')
+  }
+  return strings
+}
+
+function bufferConcat (parts) {
+  var bufs = []
+  for (var i = 0; i < parts.length; i++) {
+    var p = parts[i]
+    if (Buffer.isBuffer(p)) {
+      bufs.push(p)
+    } else if (isBufferish(p)) {
+      bufs.push(bufferFrom(p))
+    } else {
+      bufs.push(bufferFrom(String(p)))
+    }
+  }
+  return Buffer.concat(bufs)
+}
+
+function arrayConcat (parts) {
+  var res = []
+  for (var i = 0; i < parts.length; i++) {
+    res.push.apply(res, parts[i])
+  }
+  return res
+}
+
+function u8Concat (parts) {
+  var len = 0
+  for (var i = 0; i < parts.length; i++) {
+    if (typeof parts[i] === 'string') {
+      parts[i] = bufferFrom(parts[i])
+    }
+    len += parts[i].length
+  }
+  var u8 = new U8(len)
+  for (var i = 0, offset = 0; i < parts.length; i++) {
+    var part = parts[i]
+    for (var j = 0; j < part.length; j++) {
+      u8[offset++] = part[j]
+    }
+  }
+  return u8
+}
diff --git a/node_modules/concat-stream/package.json b/node_modules/concat-stream/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..f7090223487280d770e9b67b603e60aed789ecf5
--- /dev/null
+++ b/node_modules/concat-stream/package.json
@@ -0,0 +1,55 @@
+{
+  "name": "concat-stream",
+  "version": "1.6.2",
+  "description": "writable stream that concatenates strings or binary data and calls a callback with the result",
+  "tags": [
+    "stream",
+    "simple",
+    "util",
+    "utility"
+  ],
+  "author": "Max Ogden <max@maxogden.com>",
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/maxogden/concat-stream.git"
+  },
+  "bugs": {
+    "url": "http://github.com/maxogden/concat-stream/issues"
+  },
+  "engines": [
+    "node >= 0.8"
+  ],
+  "main": "index.js",
+  "files": [
+    "index.js"
+  ],
+  "scripts": {
+    "test": "tape test/*.js test/server/*.js"
+  },
+  "license": "MIT",
+  "dependencies": {
+    "buffer-from": "^1.0.0",
+    "inherits": "^2.0.3",
+    "readable-stream": "^2.2.2",
+    "typedarray": "^0.0.6"
+  },
+  "devDependencies": {
+    "tape": "^4.6.3"
+  },
+  "testling": {
+    "files": "test/*.js",
+    "browsers": [
+      "ie/8..latest",
+      "firefox/17..latest",
+      "firefox/nightly",
+      "chrome/22..latest",
+      "chrome/canary",
+      "opera/12..latest",
+      "opera/next",
+      "safari/5.1..latest",
+      "ipad/6.0..latest",
+      "iphone/6.0..latest",
+      "android-browser/4.2..latest"
+    ]
+  }
+}
diff --git a/node_modules/concat-stream/readme.md b/node_modules/concat-stream/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..7aa19c4fb104c31236f8419f421f848d7159ef8d
--- /dev/null
+++ b/node_modules/concat-stream/readme.md
@@ -0,0 +1,102 @@
+# concat-stream
+
+Writable stream that concatenates all the data from a stream and calls a callback with the result. Use this when you want to collect all the data from a stream into a single buffer.
+
+[![Build Status](https://travis-ci.org/maxogden/concat-stream.svg?branch=master)](https://travis-ci.org/maxogden/concat-stream)
+
+[![NPM](https://nodei.co/npm/concat-stream.png)](https://nodei.co/npm/concat-stream/)
+
+### description
+
+Streams emit many buffers. If you want to collect all of the buffers, and when the stream ends concatenate all of the buffers together and receive a single buffer then this is the module for you.
+
+Only use this if you know you can fit all of the output of your stream into a single Buffer (e.g. in RAM).
+
+There are also `objectMode` streams that emit things other than Buffers, and you can concatenate these too. See below for details.
+
+## Related
+
+`concat-stream` is part of the [mississippi stream utility collection](https://github.com/maxogden/mississippi) which includes more useful stream modules similar to this one.
+
+### examples
+
+#### Buffers
+
+```js
+var fs = require('fs')
+var concat = require('concat-stream')
+
+var readStream = fs.createReadStream('cat.png')
+var concatStream = concat(gotPicture)
+
+readStream.on('error', handleError)
+readStream.pipe(concatStream)
+
+function gotPicture(imageBuffer) {
+  // imageBuffer is all of `cat.png` as a node.js Buffer
+}
+
+function handleError(err) {
+  // handle your error appropriately here, e.g.:
+  console.error(err) // print the error to STDERR
+  process.exit(1) // exit program with non-zero exit code
+}
+
+```
+
+#### Arrays
+
+```js
+var write = concat(function(data) {})
+write.write([1,2,3])
+write.write([4,5,6])
+write.end()
+// data will be [1,2,3,4,5,6] in the above callback
+```
+
+#### Uint8Arrays
+
+```js
+var write = concat(function(data) {})
+var a = new Uint8Array(3)
+a[0] = 97; a[1] = 98; a[2] = 99
+write.write(a)
+write.write('!')
+write.end(Buffer.from('!!1'))
+```
+
+See `test/` for more examples
+
+# methods
+
+```js
+var concat = require('concat-stream')
+```
+
+## var writable = concat(opts={}, cb)
+
+Return a `writable` stream that will fire `cb(data)` with all of the data that
+was written to the stream. Data can be written to `writable` as strings,
+Buffers, arrays of byte integers, and Uint8Arrays. 
+
+By default `concat-stream` will give you back the same data type as the type of the first buffer written to the stream. Use `opts.encoding` to set what format `data` should be returned as, e.g. if you if you don't want to rely on the built-in type checking or for some other reason.
+
+* `string` - get a string
+* `buffer` - get back a Buffer
+* `array` - get an array of byte integers
+* `uint8array`, `u8`, `uint8` - get back a Uint8Array
+* `object`, get back an array of Objects
+
+If you don't specify an encoding, and the types can't be inferred (e.g. you write things that aren't in the list above), it will try to convert concat them into a `Buffer`.
+
+If nothing is written to `writable` then `data` will be an empty array `[]`.
+
+# error handling
+
+`concat-stream` does not handle errors for you, so you must handle errors on whatever streams you pipe into `concat-stream`. This is a general rule when programming with node.js streams: always handle errors on each and every stream. Since `concat-stream` is not itself a stream it does not emit errors.
+
+We recommend using [`end-of-stream`](https://npmjs.org/end-of-stream) or [`pump`](https://npmjs.org/pump) for writing error tolerant stream code.
+
+# license
+
+MIT LICENSE
diff --git a/node_modules/ejs/README.md b/node_modules/ejs/README.md
index 009809c13296b04a9f722e34c2c665609d61ee89..81a9aa107c59e3068e4c88bd46005f21e0a93283 100644
--- a/node_modules/ejs/README.md
+++ b/node_modules/ejs/README.md
@@ -55,12 +55,15 @@ for all the passed options. However, be aware that your code could break if we
 add an option with the same name as one of your data object's properties.
 Therefore, we do not recommend using this shortcut.
 
+### Important
+You should never give end-users unfettered access to the EJS render method, If you do so you are using EJS in an inherently un-secure way. 
+
 ### Options
 
   - `cache`                 Compiled functions are cached, requires `filename`
   - `filename`              The name of the file being rendered. Not required if you
     are using `renderFile()`. Used by `cache` to key caches, and for includes.
-  - `root`                  Set project root for includes with an absolute path (e.g, /file.ejs).
+  - `root`                  Set template root(s) for includes with an absolute path (e.g, /file.ejs).
     Can be array to try to resolve include from multiple directories.
   - `views`                 An array of paths to use when resolving includes with relative paths.
   - `context`               Function execution context
diff --git a/node_modules/ejs/bin/cli.js b/node_modules/ejs/bin/cli.js
index 0feab0b49434bbbab904198c4237c3c94b9bfc8d..cb11aa4c03c8effadd4f4020837487c9680e1435 100644
--- a/node_modules/ejs/bin/cli.js
+++ b/node_modules/ejs/bin/cli.js
@@ -17,6 +17,7 @@
  *
 */
 
+let path = require('path');
 
 let program = require('jake').program;
 delete global.jake; // NO NOT WANT
@@ -149,9 +150,6 @@ function run() {
     }
   }
 
-  // Default to having views relative from the current working directory
-  opts.views = ['.'];
-
   // Ensure there's a template to render
   if (!templatePath) {
     throw new Error('Please provide a template path. (Run ejs -h for help)');
@@ -197,7 +195,8 @@ function run() {
     vals[p] = pVals[p];
   }
 
-  let template = fs.readFileSync(templatePath).toString();
+  opts.filename = path.resolve(process.cwd(), templatePath);
+  let template = fs.readFileSync(opts.filename).toString();
   let output = ejs.render(template, vals, opts);
   if (pOpts.outputFile) {
     fs.writeFileSync(pOpts.outputFile, output);
diff --git a/node_modules/ejs/ejs.js b/node_modules/ejs/ejs.js
index 5310e76ab4a2ef109393a52337882353a78113e8..3a4af078a7a96a96e4d1659cd76cf26807ce1885 100644
--- a/node_modules/ejs/ejs.js
+++ b/node_modules/ejs/ejs.js
@@ -45,6 +45,7 @@
  * @public
  */
 
+
 var fs = require('fs');
 var path = require('path');
 var utils = require('./utils');
@@ -65,6 +66,7 @@ var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compi
 // so we make an exception for `renderFile`
 var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache');
 var _BOM = /^\uFEFF/;
+var _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
 
 /**
  * EJS template function cache. This can be a LRU object from lru-cache NPM
@@ -306,7 +308,7 @@ function fileLoader(filePath){
  */
 
 function includeFile(path, options) {
-  var opts = utils.shallowCopy({}, options);
+  var opts = utils.shallowCopy(utils.createNullProtoObjWherePossible(), options);
   opts.filename = getIncludePath(path, opts);
   if (typeof options.includer === 'function') {
     var includerResult = options.includer(path, opts.filename);
@@ -412,8 +414,8 @@ exports.compile = function compile(template, opts) {
  */
 
 exports.render = function (template, d, o) {
-  var data = d || {};
-  var opts = o || {};
+  var data = d || utils.createNullProtoObjWherePossible();
+  var opts = o || utils.createNullProtoObjWherePossible();
 
   // No options object -- if there are optiony names
   // in the data, copy them to options
@@ -484,7 +486,7 @@ exports.renderFile = function () {
     opts.filename = filename;
   }
   else {
-    data = {};
+    data = utils.createNullProtoObjWherePossible();
   }
 
   return tryHandleCache(opts, data, cb);
@@ -506,8 +508,8 @@ exports.clearCache = function () {
 };
 
 function Template(text, opts) {
-  opts = opts || {};
-  var options = {};
+  opts = opts || utils.createNullProtoObjWherePossible();
+  var options = utils.createNullProtoObjWherePossible();
   this.templateText = text;
   /** @type {string | null} */
   this.mode = null;
@@ -588,12 +590,21 @@ Template.prototype = {
         '  var __output = "";\n' +
         '  function __append(s) { if (s !== undefined && s !== null) __output += s }\n';
       if (opts.outputFunctionName) {
+        if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) {
+          throw new Error('outputFunctionName is not a valid JS identifier.');
+        }
         prepended += '  var ' + opts.outputFunctionName + ' = __append;' + '\n';
       }
+      if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) {
+        throw new Error('localsName is not a valid JS identifier.');
+      }
       if (opts.destructuredLocals && opts.destructuredLocals.length) {
         var destructuring = '  var __locals = (' + opts.localsName + ' || {}),\n';
         for (var i = 0; i < opts.destructuredLocals.length; i++) {
           var name = opts.destructuredLocals[i];
+          if (!_JS_IDENTIFIER.test(name)) {
+            throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.');
+          }
           if (i > 0) {
             destructuring += ',\n  ';
           }
@@ -684,13 +695,14 @@ Template.prototype = {
     // Adds a local `include` function which allows full recursive include
     var returnedFn = opts.client ? fn : function anonymous(data) {
       var include = function (path, includeData) {
-        var d = utils.shallowCopy({}, data);
+        var d = utils.shallowCopy(utils.createNullProtoObjWherePossible(), data);
         if (includeData) {
           d = utils.shallowCopy(d, includeData);
         }
         return includeFile(path, opts)(d);
       };
-      return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]);
+      return fn.apply(opts.context,
+        [data || utils.createNullProtoObjWherePossible(), escapeFn, include, rethrow]);
     };
     if (opts.filename && typeof Object.defineProperty === 'function') {
       var filename = opts.filename;
@@ -967,6 +979,8 @@ if (typeof window != 'undefined') {
 'use strict';
 
 var regExpChars = /[|\\{}()[\]^$+*?.]/g;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); };
 
 /**
  * Escape characters reserved in regular expressions.
@@ -1039,9 +1053,25 @@ exports.escapeXML = function (markup) {
     : String(markup)
       .replace(_MATCH_HTML, encode_char);
 };
-exports.escapeXML.toString = function () {
+
+function escapeXMLToString() {
   return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr;
-};
+}
+
+try {
+  if (typeof Object.defineProperty === 'function') {
+  // If the Function prototype is frozen, the "toString" property is non-writable. This means that any objects which inherit this property
+  // cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not using strict
+  // mode, attempting that will be silently ignored.
+  // However, we can still explicitly shadow the prototype's "toString" property by defining a new "toString" property on this object.
+    Object.defineProperty(exports.escapeXML, 'toString', { value: escapeXMLToString });
+  } else {
+    // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator.
+    exports.escapeXML.toString = escapeXMLToString;
+  }
+} catch (err) {
+  console.warn('Unable to set escapeXML.toString (is the Function prototype frozen?)');
+}
 
 /**
  * Naive copy of properties from one object to another.
@@ -1056,8 +1086,16 @@ exports.escapeXML.toString = function () {
  */
 exports.shallowCopy = function (to, from) {
   from = from || {};
-  for (var p in from) {
-    to[p] = from[p];
+  if ((to !== null) && (to !== undefined)) {
+    for (var p in from) {
+      if (!hasOwn(from, p)) {
+        continue;
+      }
+      if (p === '__proto__' || p === 'constructor') {
+        continue;
+      }
+      to[p] = from[p];
+    }
   }
   return to;
 };
@@ -1075,10 +1113,20 @@ exports.shallowCopy = function (to, from) {
  * @private
  */
 exports.shallowCopyFromList = function (to, from, list) {
-  for (var i = 0; i < list.length; i++) {
-    var p = list[i];
-    if (typeof from[p] != 'undefined') {
-      to[p] = from[p];
+  list = list || [];
+  from = from || {};
+  if ((to !== null) && (to !== undefined)) {
+    for (var i = 0; i < list.length; i++) {
+      var p = list[i];
+      if (typeof from[p] != 'undefined') {
+        if (!hasOwn(from, p)) {
+          continue;
+        }
+        if (p === '__proto__' || p === 'constructor') {
+          continue;
+        }
+        to[p] = from[p];
+      }
     }
   }
   return to;
@@ -1120,6 +1168,32 @@ exports.hyphenToCamel = function (str) {
   return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); });
 };
 
+/**
+ * Returns a null-prototype object in runtimes that support it
+ *
+ * @return {Object} Object, prototype will be set to null where possible
+ * @static
+ * @private
+ */
+exports.createNullProtoObjWherePossible = (function () {
+  if (typeof Object.create == 'function') {
+    return function () {
+      return Object.create(null);
+    };
+  }
+  if (!({__proto__: null} instanceof Object)) {
+    return function () {
+      return {__proto__: null};
+    };
+  }
+  // Not possible, just pass through
+  return function () {
+    return {};
+  };
+})();
+
+
+
 },{}],3:[function(require,module,exports){
 
 },{}],4:[function(require,module,exports){
@@ -1623,7 +1697,7 @@ module.exports={
     "engine",
     "ejs"
   ],
-  "version": "3.1.6",
+  "version": "3.1.8",
   "author": "Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)",
   "license": "Apache-2.0",
   "bin": {
@@ -1639,22 +1713,22 @@ module.exports={
   "bugs": "https://github.com/mde/ejs/issues",
   "homepage": "https://github.com/mde/ejs",
   "dependencies": {
-    "jake": "^10.6.1"
+    "jake": "^10.8.5"
   },
   "devDependencies": {
     "browserify": "^16.5.1",
     "eslint": "^6.8.0",
     "git-directory-deploy": "^1.5.1",
-    "jsdoc": "^3.6.4",
+    "jsdoc": "^4.0.2",
     "lru-cache": "^4.0.1",
-    "mocha": "^7.1.1",
+    "mocha": "^10.2.0",
     "uglify-js": "^3.3.16"
   },
   "engines": {
     "node": ">=0.10.0"
   },
   "scripts": {
-    "test": "mocha"
+    "test": "mocha -u tdd"
   }
 }
 
diff --git a/node_modules/ejs/ejs.min.js b/node_modules/ejs/ejs.min.js
index e40628cc8bd6e0e548dc3bb1bbd9b7193c58c819..f5af38935ee52c05e54f0c04c864b484e4ed91d6 100644
--- a/node_modules/ejs/ejs.min.js
+++ b/node_modules/ejs/ejs.min.js
@@ -1 +1 @@
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ejs=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r}()({1:[function(require,module,exports){"use strict";var fs=require("fs");var path=require("path");var utils=require("./utils");var scopeOptionWarned=false;var _VERSION_STRING=require("../package.json").version;var _DEFAULT_OPEN_DELIMITER="<";var _DEFAULT_CLOSE_DELIMITER=">";var _DEFAULT_DELIMITER="%";var _DEFAULT_LOCALS_NAME="locals";var _NAME="ejs";var _REGEX_STRING="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)";var _OPTS_PASSABLE_WITH_DATA=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"];var _OPTS_PASSABLE_WITH_DATA_EXPRESS=_OPTS_PASSABLE_WITH_DATA.concat("cache");var _BOM=/^\uFEFF/;exports.cache=utils.cache;exports.fileLoader=fs.readFileSync;exports.localsName=_DEFAULT_LOCALS_NAME;exports.promiseImpl=new Function("return this;")().Promise;exports.resolveInclude=function(name,filename,isDir){var dirname=path.dirname;var extname=path.extname;var resolve=path.resolve;var includePath=resolve(isDir?filename:dirname(filename),name);var ext=extname(name);if(!ext){includePath+=".ejs"}return includePath};function resolvePaths(name,paths){var filePath;if(paths.some(function(v){filePath=exports.resolveInclude(name,v,true);return fs.existsSync(filePath)})){return filePath}}function getIncludePath(path,options){var includePath;var filePath;var views=options.views;var match=/^[A-Za-z]+:\\|^\//.exec(path);if(match&&match.length){path=path.replace(/^\/*/,"");if(Array.isArray(options.root)){includePath=resolvePaths(path,options.root)}else{includePath=exports.resolveInclude(path,options.root||"/",true)}}else{if(options.filename){filePath=exports.resolveInclude(path,options.filename);if(fs.existsSync(filePath)){includePath=filePath}}if(!includePath&&Array.isArray(views)){includePath=resolvePaths(path,views)}if(!includePath&&typeof options.includer!=="function"){throw new Error('Could not find the include file "'+options.escapeFunction(path)+'"')}}return includePath}function handleCache(options,template){var func;var filename=options.filename;var hasTemplate=arguments.length>1;if(options.cache){if(!filename){throw new Error("cache option requires a filename")}func=exports.cache.get(filename);if(func){return func}if(!hasTemplate){template=fileLoader(filename).toString().replace(_BOM,"")}}else if(!hasTemplate){if(!filename){throw new Error("Internal EJS error: no file name or template "+"provided")}template=fileLoader(filename).toString().replace(_BOM,"")}func=exports.compile(template,options);if(options.cache){exports.cache.set(filename,func)}return func}function tryHandleCache(options,data,cb){var result;if(!cb){if(typeof exports.promiseImpl=="function"){return new exports.promiseImpl(function(resolve,reject){try{result=handleCache(options)(data);resolve(result)}catch(err){reject(err)}})}else{throw new Error("Please provide a callback function")}}else{try{result=handleCache(options)(data)}catch(err){return cb(err)}cb(null,result)}}function fileLoader(filePath){return exports.fileLoader(filePath)}function includeFile(path,options){var opts=utils.shallowCopy({},options);opts.filename=getIncludePath(path,opts);if(typeof options.includer==="function"){var includerResult=options.includer(path,opts.filename);if(includerResult){if(includerResult.filename){opts.filename=includerResult.filename}if(includerResult.template){return handleCache(opts,includerResult.template)}}}return handleCache(opts)}function rethrow(err,str,flnm,lineno,esc){var lines=str.split("\n");var start=Math.max(lineno-3,0);var end=Math.min(lines.length,lineno+3);var filename=esc(flnm);var context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" >> ":"    ")+curr+"| "+line}).join("\n");err.path=filename;err.message=(filename||"ejs")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err}function stripSemi(str){return str.replace(/;(\s*$)/,"$1")}exports.compile=function compile(template,opts){var templ;if(opts&&opts.scope){if(!scopeOptionWarned){console.warn("`scope` option is deprecated and will be removed in EJS 3");scopeOptionWarned=true}if(!opts.context){opts.context=opts.scope}delete opts.scope}templ=new Template(template,opts);return templ.compile()};exports.render=function(template,d,o){var data=d||{};var opts=o||{};if(arguments.length==2){utils.shallowCopyFromList(opts,data,_OPTS_PASSABLE_WITH_DATA)}return handleCache(opts,template)(data)};exports.renderFile=function(){var args=Array.prototype.slice.call(arguments);var filename=args.shift();var cb;var opts={filename:filename};var data;var viewOpts;if(typeof arguments[arguments.length-1]=="function"){cb=args.pop()}if(args.length){data=args.shift();if(args.length){utils.shallowCopy(opts,args.pop())}else{if(data.settings){if(data.settings.views){opts.views=data.settings.views}if(data.settings["view cache"]){opts.cache=true}viewOpts=data.settings["view options"];if(viewOpts){utils.shallowCopy(opts,viewOpts)}}utils.shallowCopyFromList(opts,data,_OPTS_PASSABLE_WITH_DATA_EXPRESS)}opts.filename=filename}else{data={}}return tryHandleCache(opts,data,cb)};exports.Template=Template;exports.clearCache=function(){exports.cache.reset()};function Template(text,opts){opts=opts||{};var options={};this.templateText=text;this.mode=null;this.truncate=false;this.currentLine=1;this.source="";options.client=opts.client||false;options.escapeFunction=opts.escape||opts.escapeFunction||utils.escapeXML;options.compileDebug=opts.compileDebug!==false;options.debug=!!opts.debug;options.filename=opts.filename;options.openDelimiter=opts.openDelimiter||exports.openDelimiter||_DEFAULT_OPEN_DELIMITER;options.closeDelimiter=opts.closeDelimiter||exports.closeDelimiter||_DEFAULT_CLOSE_DELIMITER;options.delimiter=opts.delimiter||exports.delimiter||_DEFAULT_DELIMITER;options.strict=opts.strict||false;options.context=opts.context;options.cache=opts.cache||false;options.rmWhitespace=opts.rmWhitespace;options.root=opts.root;options.includer=opts.includer;options.outputFunctionName=opts.outputFunctionName;options.localsName=opts.localsName||exports.localsName||_DEFAULT_LOCALS_NAME;options.views=opts.views;options.async=opts.async;options.destructuredLocals=opts.destructuredLocals;options.legacyInclude=typeof opts.legacyInclude!="undefined"?!!opts.legacyInclude:true;if(options.strict){options._with=false}else{options._with=typeof opts._with!="undefined"?opts._with:true}this.opts=options;this.regex=this.createRegex()}Template.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"};Template.prototype={createRegex:function(){var str=_REGEX_STRING;var delim=utils.escapeRegExpChars(this.opts.delimiter);var open=utils.escapeRegExpChars(this.opts.openDelimiter);var close=utils.escapeRegExpChars(this.opts.closeDelimiter);str=str.replace(/%/g,delim).replace(/</g,open).replace(/>/g,close);return new RegExp(str)},compile:function(){var src;var fn;var opts=this.opts;var prepended="";var appended="";var escapeFn=opts.escapeFunction;var ctor;var sanitizedFilename=opts.filename?JSON.stringify(opts.filename):"undefined";if(!this.source){this.generateSource();prepended+='  var __output = "";\n'+"  function __append(s) { if (s !== undefined && s !== null) __output += s }\n";if(opts.outputFunctionName){prepended+="  var "+opts.outputFunctionName+" = __append;"+"\n"}if(opts.destructuredLocals&&opts.destructuredLocals.length){var destructuring="  var __locals = ("+opts.localsName+" || {}),\n";for(var i=0;i<opts.destructuredLocals.length;i++){var name=opts.destructuredLocals[i];if(i>0){destructuring+=",\n  "}destructuring+=name+" = __locals."+name}prepended+=destructuring+";\n"}if(opts._with!==false){prepended+="  with ("+opts.localsName+" || {}) {"+"\n";appended+="  }"+"\n"}appended+="  return __output;"+"\n";this.source=prepended+this.source+appended}if(opts.compileDebug){src="var __line = 1"+"\n"+"  , __lines = "+JSON.stringify(this.templateText)+"\n"+"  , __filename = "+sanitizedFilename+";"+"\n"+"try {"+"\n"+this.source+"} catch (e) {"+"\n"+"  rethrow(e, __lines, __filename, __line, escapeFn);"+"\n"+"}"+"\n"}else{src=this.source}if(opts.client){src="escapeFn = escapeFn || "+escapeFn.toString()+";"+"\n"+src;if(opts.compileDebug){src="rethrow = rethrow || "+rethrow.toString()+";"+"\n"+src}}if(opts.strict){src='"use strict";\n'+src}if(opts.debug){console.log(src)}if(opts.compileDebug&&opts.filename){src=src+"\n"+"//# sourceURL="+sanitizedFilename+"\n"}try{if(opts.async){try{ctor=new Function("return (async function(){}).constructor;")()}catch(e){if(e instanceof SyntaxError){throw new Error("This environment does not support async/await")}else{throw e}}}else{ctor=Function}fn=new ctor(opts.localsName+", escapeFn, include, rethrow",src)}catch(e){if(e instanceof SyntaxError){if(opts.filename){e.message+=" in "+opts.filename}e.message+=" while compiling ejs\n\n";e.message+="If the above error is not helpful, you may want to try EJS-Lint:\n";e.message+="https://github.com/RyanZim/EJS-Lint";if(!opts.async){e.message+="\n";e.message+="Or, if you meant to create an async function, pass `async: true` as an option."}}throw e}var returnedFn=opts.client?fn:function anonymous(data){var include=function(path,includeData){var d=utils.shallowCopy({},data);if(includeData){d=utils.shallowCopy(d,includeData)}return includeFile(path,opts)(d)};return fn.apply(opts.context,[data||{},escapeFn,include,rethrow])};if(opts.filename&&typeof Object.defineProperty==="function"){var filename=opts.filename;var basename=path.basename(filename,path.extname(filename));try{Object.defineProperty(returnedFn,"name",{value:basename,writable:false,enumerable:false,configurable:true})}catch(e){}}return returnedFn},generateSource:function(){var opts=this.opts;if(opts.rmWhitespace){this.templateText=this.templateText.replace(/[\r\n]+/g,"\n").replace(/^\s+|\s+$/gm,"")}this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");var self=this;var matches=this.parseTemplateText();var d=this.opts.delimiter;var o=this.opts.openDelimiter;var c=this.opts.closeDelimiter;if(matches&&matches.length){matches.forEach(function(line,index){var closing;if(line.indexOf(o+d)===0&&line.indexOf(o+d+d)!==0){closing=matches[index+2];if(!(closing==d+c||closing=="-"+d+c||closing=="_"+d+c)){throw new Error('Could not find matching close tag for "'+line+'".')}}self.scanLine(line)})}},parseTemplateText:function(){var str=this.templateText;var pat=this.regex;var result=pat.exec(str);var arr=[];var firstPos;while(result){firstPos=result.index;if(firstPos!==0){arr.push(str.substring(0,firstPos));str=str.slice(firstPos)}arr.push(result[0]);str=str.slice(result[0].length);result=pat.exec(str)}if(str){arr.push(str)}return arr},_addOutput:function(line){if(this.truncate){line=line.replace(/^(?:\r\n|\r|\n)/,"");this.truncate=false}if(!line){return line}line=line.replace(/\\/g,"\\\\");line=line.replace(/\n/g,"\\n");line=line.replace(/\r/g,"\\r");line=line.replace(/"/g,'\\"');this.source+='    ; __append("'+line+'")'+"\n"},scanLine:function(line){var self=this;var d=this.opts.delimiter;var o=this.opts.openDelimiter;var c=this.opts.closeDelimiter;var newLineCount=0;newLineCount=line.split("\n").length-1;switch(line){case o+d:case o+d+"_":this.mode=Template.modes.EVAL;break;case o+d+"=":this.mode=Template.modes.ESCAPED;break;case o+d+"-":this.mode=Template.modes.RAW;break;case o+d+"#":this.mode=Template.modes.COMMENT;break;case o+d+d:this.mode=Template.modes.LITERAL;this.source+='    ; __append("'+line.replace(o+d+d,o+d)+'")'+"\n";break;case d+d+c:this.mode=Template.modes.LITERAL;this.source+='    ; __append("'+line.replace(d+d+c,d+c)+'")'+"\n";break;case d+c:case"-"+d+c:case"_"+d+c:if(this.mode==Template.modes.LITERAL){this._addOutput(line)}this.mode=null;this.truncate=line.indexOf("-")===0||line.indexOf("_")===0;break;default:if(this.mode){switch(this.mode){case Template.modes.EVAL:case Template.modes.ESCAPED:case Template.modes.RAW:if(line.lastIndexOf("//")>line.lastIndexOf("\n")){line+="\n"}}switch(this.mode){case Template.modes.EVAL:this.source+="    ; "+line+"\n";break;case Template.modes.ESCAPED:this.source+="    ; __append(escapeFn("+stripSemi(line)+"))"+"\n";break;case Template.modes.RAW:this.source+="    ; __append("+stripSemi(line)+")"+"\n";break;case Template.modes.COMMENT:break;case Template.modes.LITERAL:this._addOutput(line);break}}else{this._addOutput(line)}}if(self.opts.compileDebug&&newLineCount){this.currentLine+=newLineCount;this.source+="    ; __line = "+this.currentLine+"\n"}}};exports.escapeXML=utils.escapeXML;exports.__express=exports.renderFile;exports.VERSION=_VERSION_STRING;exports.name=_NAME;if(typeof window!="undefined"){window.ejs=exports}},{"../package.json":6,"./utils":2,fs:3,path:4}],2:[function(require,module,exports){"use strict";var regExpChars=/[|\\{}()[\]^$+*?.]/g;exports.escapeRegExpChars=function(string){if(!string){return""}return String(string).replace(regExpChars,"\\$&")};var _ENCODE_HTML_RULES={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&#34;","'":"&#39;"};var _MATCH_HTML=/[&<>'"]/g;function encode_char(c){return _ENCODE_HTML_RULES[c]||c}var escapeFuncStr="var _ENCODE_HTML_RULES = {\n"+'      "&": "&amp;"\n'+'    , "<": "&lt;"\n'+'    , ">": "&gt;"\n'+'    , \'"\': "&#34;"\n'+'    , "\'": "&#39;"\n'+"    }\n"+"  , _MATCH_HTML = /[&<>'\"]/g;\n"+"function encode_char(c) {\n"+"  return _ENCODE_HTML_RULES[c] || c;\n"+"};\n";exports.escapeXML=function(markup){return markup==undefined?"":String(markup).replace(_MATCH_HTML,encode_char)};exports.escapeXML.toString=function(){return Function.prototype.toString.call(this)+";\n"+escapeFuncStr};exports.shallowCopy=function(to,from){from=from||{};for(var p in from){to[p]=from[p]}return to};exports.shallowCopyFromList=function(to,from,list){for(var i=0;i<list.length;i++){var p=list[i];if(typeof from[p]!="undefined"){to[p]=from[p]}}return to};exports.cache={_data:{},set:function(key,val){this._data[key]=val},get:function(key){return this._data[key]},remove:function(key){delete this._data[key]},reset:function(){this._data={}}};exports.hyphenToCamel=function(str){return str.replace(/-[a-z]/g,function(match){return match[1].toUpperCase()})}},{}],3:[function(require,module,exports){},{}],4:[function(require,module,exports){(function(process){function normalizeArray(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift("..")}}return parts}exports.resolve=function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:process.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){continue}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=normalizeArray(filter(resolvedPath.split("/"),function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==="/";path=normalizeArray(filter(path.split("/"),function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path};exports.isAbsolute=function(path){return path.charAt(0)==="/"};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=="string"){throw new TypeError("Arguments to path.join must be strings")}return p}).join("/"))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=="")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push("..")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join("/")};exports.sep="/";exports.delimiter=":";exports.dirname=function(path){if(typeof path!=="string")path=path+"";if(path.length===0)return".";var code=path.charCodeAt(0);var hasRoot=code===47;var end=-1;var matchedSlash=true;for(var i=path.length-1;i>=1;--i){code=path.charCodeAt(i);if(code===47){if(!matchedSlash){end=i;break}}else{matchedSlash=false}}if(end===-1)return hasRoot?"/":".";if(hasRoot&&end===1){return"/"}return path.slice(0,end)};function basename(path){if(typeof path!=="string")path=path+"";var start=0;var end=-1;var matchedSlash=true;var i;for(i=path.length-1;i>=0;--i){if(path.charCodeAt(i)===47){if(!matchedSlash){start=i+1;break}}else if(end===-1){matchedSlash=false;end=i+1}}if(end===-1)return"";return path.slice(start,end)}exports.basename=function(path,ext){var f=basename(path);if(ext&&f.substr(-1*ext.length)===ext){f=f.substr(0,f.length-ext.length)}return f};exports.extname=function(path){if(typeof path!=="string")path=path+"";var startDot=-1;var startPart=0;var end=-1;var matchedSlash=true;var preDotState=0;for(var i=path.length-1;i>=0;--i){var code=path.charCodeAt(i);if(code===47){if(!matchedSlash){startPart=i+1;break}continue}if(end===-1){matchedSlash=false;end=i+1}if(code===46){if(startDot===-1)startDot=i;else if(preDotState!==1)preDotState=1}else if(startDot!==-1){preDotState=-1}}if(startDot===-1||end===-1||preDotState===0||preDotState===1&&startDot===end-1&&startDot===startPart+1){return""}return path.slice(startDot,end)};function filter(xs,f){if(xs.filter)return xs.filter(f);var res=[];for(var i=0;i<xs.length;i++){if(f(xs[i],i,xs))res.push(xs[i])}return res}var substr="ab".substr(-1)==="b"?function(str,start,len){return str.substr(start,len)}:function(str,start,len){if(start<0)start=str.length+start;return str.substr(start,len)}}).call(this,require("_process"))},{_process:5}],5:[function(require,module,exports){var process=module.exports={};var cachedSetTimeout;var cachedClearTimeout;function defaultSetTimout(){throw new Error("setTimeout has not been defined")}function defaultClearTimeout(){throw new Error("clearTimeout has not been defined")}(function(){try{if(typeof setTimeout==="function"){cachedSetTimeout=setTimeout}else{cachedSetTimeout=defaultSetTimout}}catch(e){cachedSetTimeout=defaultSetTimout}try{if(typeof clearTimeout==="function"){cachedClearTimeout=clearTimeout}else{cachedClearTimeout=defaultClearTimeout}}catch(e){cachedClearTimeout=defaultClearTimeout}})();function runTimeout(fun){if(cachedSetTimeout===setTimeout){return setTimeout(fun,0)}if((cachedSetTimeout===defaultSetTimout||!cachedSetTimeout)&&setTimeout){cachedSetTimeout=setTimeout;return setTimeout(fun,0)}try{return cachedSetTimeout(fun,0)}catch(e){try{return cachedSetTimeout.call(null,fun,0)}catch(e){return cachedSetTimeout.call(this,fun,0)}}}function runClearTimeout(marker){if(cachedClearTimeout===clearTimeout){return clearTimeout(marker)}if((cachedClearTimeout===defaultClearTimeout||!cachedClearTimeout)&&clearTimeout){cachedClearTimeout=clearTimeout;return clearTimeout(marker)}try{return cachedClearTimeout(marker)}catch(e){try{return cachedClearTimeout.call(null,marker)}catch(e){return cachedClearTimeout.call(this,marker)}}}var queue=[];var draining=false;var currentQueue;var queueIndex=-1;function cleanUpNextTick(){if(!draining||!currentQueue){return}draining=false;if(currentQueue.length){queue=currentQueue.concat(queue)}else{queueIndex=-1}if(queue.length){drainQueue()}}function drainQueue(){if(draining){return}var timeout=runTimeout(cleanUpNextTick);draining=true;var len=queue.length;while(len){currentQueue=queue;queue=[];while(++queueIndex<len){if(currentQueue){currentQueue[queueIndex].run()}}queueIndex=-1;len=queue.length}currentQueue=null;draining=false;runClearTimeout(timeout)}process.nextTick=function(fun){var args=new Array(arguments.length-1);if(arguments.length>1){for(var i=1;i<arguments.length;i++){args[i-1]=arguments[i]}}queue.push(new Item(fun,args));if(queue.length===1&&!draining){runTimeout(drainQueue)}};function Item(fun,array){this.fun=fun;this.array=array}Item.prototype.run=function(){this.fun.apply(null,this.array)};process.title="browser";process.browser=true;process.env={};process.argv=[];process.version="";process.versions={};function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.prependListener=noop;process.prependOnceListener=noop;process.listeners=function(name){return[]};process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")};process.umask=function(){return 0}},{}],6:[function(require,module,exports){module.exports={name:"ejs",description:"Embedded JavaScript templates",keywords:["template","engine","ejs"],version:"3.1.6",author:"Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)",license:"Apache-2.0",bin:{ejs:"./bin/cli.js"},main:"./lib/ejs.js",jsdelivr:"ejs.min.js",unpkg:"ejs.min.js",repository:{type:"git",url:"git://github.com/mde/ejs.git"},bugs:"https://github.com/mde/ejs/issues",homepage:"https://github.com/mde/ejs",dependencies:{jake:"^10.6.1"},devDependencies:{browserify:"^16.5.1",eslint:"^6.8.0","git-directory-deploy":"^1.5.1",jsdoc:"^3.6.4","lru-cache":"^4.0.1",mocha:"^7.1.1","uglify-js":"^3.3.16"},engines:{node:">=0.10.0"},scripts:{test:"mocha"}}},{}]},{},[1])(1)});
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ejs=f()}})(function(){var define,module,exports;return function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r}()({1:[function(require,module,exports){"use strict";var fs=require("fs");var path=require("path");var utils=require("./utils");var scopeOptionWarned=false;var _VERSION_STRING=require("../package.json").version;var _DEFAULT_OPEN_DELIMITER="<";var _DEFAULT_CLOSE_DELIMITER=">";var _DEFAULT_DELIMITER="%";var _DEFAULT_LOCALS_NAME="locals";var _NAME="ejs";var _REGEX_STRING="(<%%|%%>|<%=|<%-|<%_|<%#|<%|%>|-%>|_%>)";var _OPTS_PASSABLE_WITH_DATA=["delimiter","scope","context","debug","compileDebug","client","_with","rmWhitespace","strict","filename","async"];var _OPTS_PASSABLE_WITH_DATA_EXPRESS=_OPTS_PASSABLE_WITH_DATA.concat("cache");var _BOM=/^\uFEFF/;var _JS_IDENTIFIER=/^[a-zA-Z_$][0-9a-zA-Z_$]*$/;exports.cache=utils.cache;exports.fileLoader=fs.readFileSync;exports.localsName=_DEFAULT_LOCALS_NAME;exports.promiseImpl=new Function("return this;")().Promise;exports.resolveInclude=function(name,filename,isDir){var dirname=path.dirname;var extname=path.extname;var resolve=path.resolve;var includePath=resolve(isDir?filename:dirname(filename),name);var ext=extname(name);if(!ext){includePath+=".ejs"}return includePath};function resolvePaths(name,paths){var filePath;if(paths.some(function(v){filePath=exports.resolveInclude(name,v,true);return fs.existsSync(filePath)})){return filePath}}function getIncludePath(path,options){var includePath;var filePath;var views=options.views;var match=/^[A-Za-z]+:\\|^\//.exec(path);if(match&&match.length){path=path.replace(/^\/*/,"");if(Array.isArray(options.root)){includePath=resolvePaths(path,options.root)}else{includePath=exports.resolveInclude(path,options.root||"/",true)}}else{if(options.filename){filePath=exports.resolveInclude(path,options.filename);if(fs.existsSync(filePath)){includePath=filePath}}if(!includePath&&Array.isArray(views)){includePath=resolvePaths(path,views)}if(!includePath&&typeof options.includer!=="function"){throw new Error('Could not find the include file "'+options.escapeFunction(path)+'"')}}return includePath}function handleCache(options,template){var func;var filename=options.filename;var hasTemplate=arguments.length>1;if(options.cache){if(!filename){throw new Error("cache option requires a filename")}func=exports.cache.get(filename);if(func){return func}if(!hasTemplate){template=fileLoader(filename).toString().replace(_BOM,"")}}else if(!hasTemplate){if(!filename){throw new Error("Internal EJS error: no file name or template "+"provided")}template=fileLoader(filename).toString().replace(_BOM,"")}func=exports.compile(template,options);if(options.cache){exports.cache.set(filename,func)}return func}function tryHandleCache(options,data,cb){var result;if(!cb){if(typeof exports.promiseImpl=="function"){return new exports.promiseImpl(function(resolve,reject){try{result=handleCache(options)(data);resolve(result)}catch(err){reject(err)}})}else{throw new Error("Please provide a callback function")}}else{try{result=handleCache(options)(data)}catch(err){return cb(err)}cb(null,result)}}function fileLoader(filePath){return exports.fileLoader(filePath)}function includeFile(path,options){var opts=utils.shallowCopy(utils.createNullProtoObjWherePossible(),options);opts.filename=getIncludePath(path,opts);if(typeof options.includer==="function"){var includerResult=options.includer(path,opts.filename);if(includerResult){if(includerResult.filename){opts.filename=includerResult.filename}if(includerResult.template){return handleCache(opts,includerResult.template)}}}return handleCache(opts)}function rethrow(err,str,flnm,lineno,esc){var lines=str.split("\n");var start=Math.max(lineno-3,0);var end=Math.min(lines.length,lineno+3);var filename=esc(flnm);var context=lines.slice(start,end).map(function(line,i){var curr=i+start+1;return(curr==lineno?" >> ":"    ")+curr+"| "+line}).join("\n");err.path=filename;err.message=(filename||"ejs")+":"+lineno+"\n"+context+"\n\n"+err.message;throw err}function stripSemi(str){return str.replace(/;(\s*$)/,"$1")}exports.compile=function compile(template,opts){var templ;if(opts&&opts.scope){if(!scopeOptionWarned){console.warn("`scope` option is deprecated and will be removed in EJS 3");scopeOptionWarned=true}if(!opts.context){opts.context=opts.scope}delete opts.scope}templ=new Template(template,opts);return templ.compile()};exports.render=function(template,d,o){var data=d||utils.createNullProtoObjWherePossible();var opts=o||utils.createNullProtoObjWherePossible();if(arguments.length==2){utils.shallowCopyFromList(opts,data,_OPTS_PASSABLE_WITH_DATA)}return handleCache(opts,template)(data)};exports.renderFile=function(){var args=Array.prototype.slice.call(arguments);var filename=args.shift();var cb;var opts={filename:filename};var data;var viewOpts;if(typeof arguments[arguments.length-1]=="function"){cb=args.pop()}if(args.length){data=args.shift();if(args.length){utils.shallowCopy(opts,args.pop())}else{if(data.settings){if(data.settings.views){opts.views=data.settings.views}if(data.settings["view cache"]){opts.cache=true}viewOpts=data.settings["view options"];if(viewOpts){utils.shallowCopy(opts,viewOpts)}}utils.shallowCopyFromList(opts,data,_OPTS_PASSABLE_WITH_DATA_EXPRESS)}opts.filename=filename}else{data=utils.createNullProtoObjWherePossible()}return tryHandleCache(opts,data,cb)};exports.Template=Template;exports.clearCache=function(){exports.cache.reset()};function Template(text,opts){opts=opts||utils.createNullProtoObjWherePossible();var options=utils.createNullProtoObjWherePossible();this.templateText=text;this.mode=null;this.truncate=false;this.currentLine=1;this.source="";options.client=opts.client||false;options.escapeFunction=opts.escape||opts.escapeFunction||utils.escapeXML;options.compileDebug=opts.compileDebug!==false;options.debug=!!opts.debug;options.filename=opts.filename;options.openDelimiter=opts.openDelimiter||exports.openDelimiter||_DEFAULT_OPEN_DELIMITER;options.closeDelimiter=opts.closeDelimiter||exports.closeDelimiter||_DEFAULT_CLOSE_DELIMITER;options.delimiter=opts.delimiter||exports.delimiter||_DEFAULT_DELIMITER;options.strict=opts.strict||false;options.context=opts.context;options.cache=opts.cache||false;options.rmWhitespace=opts.rmWhitespace;options.root=opts.root;options.includer=opts.includer;options.outputFunctionName=opts.outputFunctionName;options.localsName=opts.localsName||exports.localsName||_DEFAULT_LOCALS_NAME;options.views=opts.views;options.async=opts.async;options.destructuredLocals=opts.destructuredLocals;options.legacyInclude=typeof opts.legacyInclude!="undefined"?!!opts.legacyInclude:true;if(options.strict){options._with=false}else{options._with=typeof opts._with!="undefined"?opts._with:true}this.opts=options;this.regex=this.createRegex()}Template.modes={EVAL:"eval",ESCAPED:"escaped",RAW:"raw",COMMENT:"comment",LITERAL:"literal"};Template.prototype={createRegex:function(){var str=_REGEX_STRING;var delim=utils.escapeRegExpChars(this.opts.delimiter);var open=utils.escapeRegExpChars(this.opts.openDelimiter);var close=utils.escapeRegExpChars(this.opts.closeDelimiter);str=str.replace(/%/g,delim).replace(/</g,open).replace(/>/g,close);return new RegExp(str)},compile:function(){var src;var fn;var opts=this.opts;var prepended="";var appended="";var escapeFn=opts.escapeFunction;var ctor;var sanitizedFilename=opts.filename?JSON.stringify(opts.filename):"undefined";if(!this.source){this.generateSource();prepended+='  var __output = "";\n'+"  function __append(s) { if (s !== undefined && s !== null) __output += s }\n";if(opts.outputFunctionName){if(!_JS_IDENTIFIER.test(opts.outputFunctionName)){throw new Error("outputFunctionName is not a valid JS identifier.")}prepended+="  var "+opts.outputFunctionName+" = __append;"+"\n"}if(opts.localsName&&!_JS_IDENTIFIER.test(opts.localsName)){throw new Error("localsName is not a valid JS identifier.")}if(opts.destructuredLocals&&opts.destructuredLocals.length){var destructuring="  var __locals = ("+opts.localsName+" || {}),\n";for(var i=0;i<opts.destructuredLocals.length;i++){var name=opts.destructuredLocals[i];if(!_JS_IDENTIFIER.test(name)){throw new Error("destructuredLocals["+i+"] is not a valid JS identifier.")}if(i>0){destructuring+=",\n  "}destructuring+=name+" = __locals."+name}prepended+=destructuring+";\n"}if(opts._with!==false){prepended+="  with ("+opts.localsName+" || {}) {"+"\n";appended+="  }"+"\n"}appended+="  return __output;"+"\n";this.source=prepended+this.source+appended}if(opts.compileDebug){src="var __line = 1"+"\n"+"  , __lines = "+JSON.stringify(this.templateText)+"\n"+"  , __filename = "+sanitizedFilename+";"+"\n"+"try {"+"\n"+this.source+"} catch (e) {"+"\n"+"  rethrow(e, __lines, __filename, __line, escapeFn);"+"\n"+"}"+"\n"}else{src=this.source}if(opts.client){src="escapeFn = escapeFn || "+escapeFn.toString()+";"+"\n"+src;if(opts.compileDebug){src="rethrow = rethrow || "+rethrow.toString()+";"+"\n"+src}}if(opts.strict){src='"use strict";\n'+src}if(opts.debug){console.log(src)}if(opts.compileDebug&&opts.filename){src=src+"\n"+"//# sourceURL="+sanitizedFilename+"\n"}try{if(opts.async){try{ctor=new Function("return (async function(){}).constructor;")()}catch(e){if(e instanceof SyntaxError){throw new Error("This environment does not support async/await")}else{throw e}}}else{ctor=Function}fn=new ctor(opts.localsName+", escapeFn, include, rethrow",src)}catch(e){if(e instanceof SyntaxError){if(opts.filename){e.message+=" in "+opts.filename}e.message+=" while compiling ejs\n\n";e.message+="If the above error is not helpful, you may want to try EJS-Lint:\n";e.message+="https://github.com/RyanZim/EJS-Lint";if(!opts.async){e.message+="\n";e.message+="Or, if you meant to create an async function, pass `async: true` as an option."}}throw e}var returnedFn=opts.client?fn:function anonymous(data){var include=function(path,includeData){var d=utils.shallowCopy(utils.createNullProtoObjWherePossible(),data);if(includeData){d=utils.shallowCopy(d,includeData)}return includeFile(path,opts)(d)};return fn.apply(opts.context,[data||utils.createNullProtoObjWherePossible(),escapeFn,include,rethrow])};if(opts.filename&&typeof Object.defineProperty==="function"){var filename=opts.filename;var basename=path.basename(filename,path.extname(filename));try{Object.defineProperty(returnedFn,"name",{value:basename,writable:false,enumerable:false,configurable:true})}catch(e){}}return returnedFn},generateSource:function(){var opts=this.opts;if(opts.rmWhitespace){this.templateText=this.templateText.replace(/[\r\n]+/g,"\n").replace(/^\s+|\s+$/gm,"")}this.templateText=this.templateText.replace(/[ \t]*<%_/gm,"<%_").replace(/_%>[ \t]*/gm,"_%>");var self=this;var matches=this.parseTemplateText();var d=this.opts.delimiter;var o=this.opts.openDelimiter;var c=this.opts.closeDelimiter;if(matches&&matches.length){matches.forEach(function(line,index){var closing;if(line.indexOf(o+d)===0&&line.indexOf(o+d+d)!==0){closing=matches[index+2];if(!(closing==d+c||closing=="-"+d+c||closing=="_"+d+c)){throw new Error('Could not find matching close tag for "'+line+'".')}}self.scanLine(line)})}},parseTemplateText:function(){var str=this.templateText;var pat=this.regex;var result=pat.exec(str);var arr=[];var firstPos;while(result){firstPos=result.index;if(firstPos!==0){arr.push(str.substring(0,firstPos));str=str.slice(firstPos)}arr.push(result[0]);str=str.slice(result[0].length);result=pat.exec(str)}if(str){arr.push(str)}return arr},_addOutput:function(line){if(this.truncate){line=line.replace(/^(?:\r\n|\r|\n)/,"");this.truncate=false}if(!line){return line}line=line.replace(/\\/g,"\\\\");line=line.replace(/\n/g,"\\n");line=line.replace(/\r/g,"\\r");line=line.replace(/"/g,'\\"');this.source+='    ; __append("'+line+'")'+"\n"},scanLine:function(line){var self=this;var d=this.opts.delimiter;var o=this.opts.openDelimiter;var c=this.opts.closeDelimiter;var newLineCount=0;newLineCount=line.split("\n").length-1;switch(line){case o+d:case o+d+"_":this.mode=Template.modes.EVAL;break;case o+d+"=":this.mode=Template.modes.ESCAPED;break;case o+d+"-":this.mode=Template.modes.RAW;break;case o+d+"#":this.mode=Template.modes.COMMENT;break;case o+d+d:this.mode=Template.modes.LITERAL;this.source+='    ; __append("'+line.replace(o+d+d,o+d)+'")'+"\n";break;case d+d+c:this.mode=Template.modes.LITERAL;this.source+='    ; __append("'+line.replace(d+d+c,d+c)+'")'+"\n";break;case d+c:case"-"+d+c:case"_"+d+c:if(this.mode==Template.modes.LITERAL){this._addOutput(line)}this.mode=null;this.truncate=line.indexOf("-")===0||line.indexOf("_")===0;break;default:if(this.mode){switch(this.mode){case Template.modes.EVAL:case Template.modes.ESCAPED:case Template.modes.RAW:if(line.lastIndexOf("//")>line.lastIndexOf("\n")){line+="\n"}}switch(this.mode){case Template.modes.EVAL:this.source+="    ; "+line+"\n";break;case Template.modes.ESCAPED:this.source+="    ; __append(escapeFn("+stripSemi(line)+"))"+"\n";break;case Template.modes.RAW:this.source+="    ; __append("+stripSemi(line)+")"+"\n";break;case Template.modes.COMMENT:break;case Template.modes.LITERAL:this._addOutput(line);break}}else{this._addOutput(line)}}if(self.opts.compileDebug&&newLineCount){this.currentLine+=newLineCount;this.source+="    ; __line = "+this.currentLine+"\n"}}};exports.escapeXML=utils.escapeXML;exports.__express=exports.renderFile;exports.VERSION=_VERSION_STRING;exports.name=_NAME;if(typeof window!="undefined"){window.ejs=exports}},{"../package.json":6,"./utils":2,fs:3,path:4}],2:[function(require,module,exports){"use strict";var regExpChars=/[|\\{}()[\]^$+*?.]/g;var hasOwnProperty=Object.prototype.hasOwnProperty;var hasOwn=function(obj,key){return hasOwnProperty.apply(obj,[key])};exports.escapeRegExpChars=function(string){if(!string){return""}return String(string).replace(regExpChars,"\\$&")};var _ENCODE_HTML_RULES={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&#34;","'":"&#39;"};var _MATCH_HTML=/[&<>'"]/g;function encode_char(c){return _ENCODE_HTML_RULES[c]||c}var escapeFuncStr="var _ENCODE_HTML_RULES = {\n"+'      "&": "&amp;"\n'+'    , "<": "&lt;"\n'+'    , ">": "&gt;"\n'+'    , \'"\': "&#34;"\n'+'    , "\'": "&#39;"\n'+"    }\n"+"  , _MATCH_HTML = /[&<>'\"]/g;\n"+"function encode_char(c) {\n"+"  return _ENCODE_HTML_RULES[c] || c;\n"+"};\n";exports.escapeXML=function(markup){return markup==undefined?"":String(markup).replace(_MATCH_HTML,encode_char)};function escapeXMLToString(){return Function.prototype.toString.call(this)+";\n"+escapeFuncStr}try{if(typeof Object.defineProperty==="function"){Object.defineProperty(exports.escapeXML,"toString",{value:escapeXMLToString})}else{exports.escapeXML.toString=escapeXMLToString}}catch(err){console.warn("Unable to set escapeXML.toString (is the Function prototype frozen?)")}exports.shallowCopy=function(to,from){from=from||{};if(to!==null&&to!==undefined){for(var p in from){if(!hasOwn(from,p)){continue}if(p==="__proto__"||p==="constructor"){continue}to[p]=from[p]}}return to};exports.shallowCopyFromList=function(to,from,list){list=list||[];from=from||{};if(to!==null&&to!==undefined){for(var i=0;i<list.length;i++){var p=list[i];if(typeof from[p]!="undefined"){if(!hasOwn(from,p)){continue}if(p==="__proto__"||p==="constructor"){continue}to[p]=from[p]}}}return to};exports.cache={_data:{},set:function(key,val){this._data[key]=val},get:function(key){return this._data[key]},remove:function(key){delete this._data[key]},reset:function(){this._data={}}};exports.hyphenToCamel=function(str){return str.replace(/-[a-z]/g,function(match){return match[1].toUpperCase()})};exports.createNullProtoObjWherePossible=function(){if(typeof Object.create=="function"){return function(){return Object.create(null)}}if(!({__proto__:null}instanceof Object)){return function(){return{__proto__:null}}}return function(){return{}}}()},{}],3:[function(require,module,exports){},{}],4:[function(require,module,exports){(function(process){function normalizeArray(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up--;up){parts.unshift("..")}}return parts}exports.resolve=function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:process.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){continue}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=normalizeArray(filter(resolvedPath.split("/"),function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."};exports.normalize=function(path){var isAbsolute=exports.isAbsolute(path),trailingSlash=substr(path,-1)==="/";path=normalizeArray(filter(path.split("/"),function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path};exports.isAbsolute=function(path){return path.charAt(0)==="/"};exports.join=function(){var paths=Array.prototype.slice.call(arguments,0);return exports.normalize(filter(paths,function(p,index){if(typeof p!=="string"){throw new TypeError("Arguments to path.join must be strings")}return p}).join("/"))};exports.relative=function(from,to){from=exports.resolve(from).substr(1);to=exports.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=="")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push("..")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join("/")};exports.sep="/";exports.delimiter=":";exports.dirname=function(path){if(typeof path!=="string")path=path+"";if(path.length===0)return".";var code=path.charCodeAt(0);var hasRoot=code===47;var end=-1;var matchedSlash=true;for(var i=path.length-1;i>=1;--i){code=path.charCodeAt(i);if(code===47){if(!matchedSlash){end=i;break}}else{matchedSlash=false}}if(end===-1)return hasRoot?"/":".";if(hasRoot&&end===1){return"/"}return path.slice(0,end)};function basename(path){if(typeof path!=="string")path=path+"";var start=0;var end=-1;var matchedSlash=true;var i;for(i=path.length-1;i>=0;--i){if(path.charCodeAt(i)===47){if(!matchedSlash){start=i+1;break}}else if(end===-1){matchedSlash=false;end=i+1}}if(end===-1)return"";return path.slice(start,end)}exports.basename=function(path,ext){var f=basename(path);if(ext&&f.substr(-1*ext.length)===ext){f=f.substr(0,f.length-ext.length)}return f};exports.extname=function(path){if(typeof path!=="string")path=path+"";var startDot=-1;var startPart=0;var end=-1;var matchedSlash=true;var preDotState=0;for(var i=path.length-1;i>=0;--i){var code=path.charCodeAt(i);if(code===47){if(!matchedSlash){startPart=i+1;break}continue}if(end===-1){matchedSlash=false;end=i+1}if(code===46){if(startDot===-1)startDot=i;else if(preDotState!==1)preDotState=1}else if(startDot!==-1){preDotState=-1}}if(startDot===-1||end===-1||preDotState===0||preDotState===1&&startDot===end-1&&startDot===startPart+1){return""}return path.slice(startDot,end)};function filter(xs,f){if(xs.filter)return xs.filter(f);var res=[];for(var i=0;i<xs.length;i++){if(f(xs[i],i,xs))res.push(xs[i])}return res}var substr="ab".substr(-1)==="b"?function(str,start,len){return str.substr(start,len)}:function(str,start,len){if(start<0)start=str.length+start;return str.substr(start,len)}}).call(this,require("_process"))},{_process:5}],5:[function(require,module,exports){var process=module.exports={};var cachedSetTimeout;var cachedClearTimeout;function defaultSetTimout(){throw new Error("setTimeout has not been defined")}function defaultClearTimeout(){throw new Error("clearTimeout has not been defined")}(function(){try{if(typeof setTimeout==="function"){cachedSetTimeout=setTimeout}else{cachedSetTimeout=defaultSetTimout}}catch(e){cachedSetTimeout=defaultSetTimout}try{if(typeof clearTimeout==="function"){cachedClearTimeout=clearTimeout}else{cachedClearTimeout=defaultClearTimeout}}catch(e){cachedClearTimeout=defaultClearTimeout}})();function runTimeout(fun){if(cachedSetTimeout===setTimeout){return setTimeout(fun,0)}if((cachedSetTimeout===defaultSetTimout||!cachedSetTimeout)&&setTimeout){cachedSetTimeout=setTimeout;return setTimeout(fun,0)}try{return cachedSetTimeout(fun,0)}catch(e){try{return cachedSetTimeout.call(null,fun,0)}catch(e){return cachedSetTimeout.call(this,fun,0)}}}function runClearTimeout(marker){if(cachedClearTimeout===clearTimeout){return clearTimeout(marker)}if((cachedClearTimeout===defaultClearTimeout||!cachedClearTimeout)&&clearTimeout){cachedClearTimeout=clearTimeout;return clearTimeout(marker)}try{return cachedClearTimeout(marker)}catch(e){try{return cachedClearTimeout.call(null,marker)}catch(e){return cachedClearTimeout.call(this,marker)}}}var queue=[];var draining=false;var currentQueue;var queueIndex=-1;function cleanUpNextTick(){if(!draining||!currentQueue){return}draining=false;if(currentQueue.length){queue=currentQueue.concat(queue)}else{queueIndex=-1}if(queue.length){drainQueue()}}function drainQueue(){if(draining){return}var timeout=runTimeout(cleanUpNextTick);draining=true;var len=queue.length;while(len){currentQueue=queue;queue=[];while(++queueIndex<len){if(currentQueue){currentQueue[queueIndex].run()}}queueIndex=-1;len=queue.length}currentQueue=null;draining=false;runClearTimeout(timeout)}process.nextTick=function(fun){var args=new Array(arguments.length-1);if(arguments.length>1){for(var i=1;i<arguments.length;i++){args[i-1]=arguments[i]}}queue.push(new Item(fun,args));if(queue.length===1&&!draining){runTimeout(drainQueue)}};function Item(fun,array){this.fun=fun;this.array=array}Item.prototype.run=function(){this.fun.apply(null,this.array)};process.title="browser";process.browser=true;process.env={};process.argv=[];process.version="";process.versions={};function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.prependListener=noop;process.prependOnceListener=noop;process.listeners=function(name){return[]};process.binding=function(name){throw new Error("process.binding is not supported")};process.cwd=function(){return"/"};process.chdir=function(dir){throw new Error("process.chdir is not supported")};process.umask=function(){return 0}},{}],6:[function(require,module,exports){module.exports={name:"ejs",description:"Embedded JavaScript templates",keywords:["template","engine","ejs"],version:"3.1.8",author:"Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)",license:"Apache-2.0",bin:{ejs:"./bin/cli.js"},main:"./lib/ejs.js",jsdelivr:"ejs.min.js",unpkg:"ejs.min.js",repository:{type:"git",url:"git://github.com/mde/ejs.git"},bugs:"https://github.com/mde/ejs/issues",homepage:"https://github.com/mde/ejs",dependencies:{jake:"^10.8.5"},devDependencies:{browserify:"^16.5.1",eslint:"^6.8.0","git-directory-deploy":"^1.5.1",jsdoc:"^4.0.2","lru-cache":"^4.0.1",mocha:"^10.2.0","uglify-js":"^3.3.16"},engines:{node:">=0.10.0"},scripts:{test:"mocha -u tdd"}}},{}]},{},[1])(1)});
diff --git a/node_modules/ejs/jakefile.js b/node_modules/ejs/jakefile.js
index 3953160af2546da0be95f6cb1d53c0059c59f6a0..7f6010518cabd6e3d23a74ecab65a5dd3a76ecc1 100644
--- a/node_modules/ejs/jakefile.js
+++ b/node_modules/ejs/jakefile.js
@@ -1,4 +1,5 @@
 var fs = require('fs');
+var path = require('path');
 var execSync = require('child_process').execSync;
 var exec = function (cmd) {
   execSync(cmd, {stdio: 'inherit'});
@@ -19,31 +20,36 @@ task('clean', ['clobber'], function () {
 
 desc('Lints the source code');
 task('lint', ['clean'], function () {
-  exec('./node_modules/.bin/eslint "**/*.js"');
+  var epath = path.join('./node_modules/.bin/eslint');
+  exec(epath+' "**/*.js"');
   console.log('Linting completed.');
 });
 
 task('browserify', function () {
-  exec('./node_modules/browserify/bin/cmd.js --standalone ejs lib/ejs.js > ejs.js');
+  var epath = path.join('./node_modules/browserify/bin/cmd.js');
+  exec(epath+' --standalone ejs lib/ejs.js > ejs.js');
   console.log('Browserification completed.');
 });
 
 task('minify', function () {
-  exec('./node_modules/uglify-js/bin/uglifyjs ejs.js > ejs.min.js');
+  var epath = path.join('./node_modules/uglify-js/bin/uglifyjs');
+  exec(epath+' ejs.js > ejs.min.js');
   console.log('Minification completed.');
 });
 
 desc('Generates the EJS API docs for the public API');
 task('doc', function () {
   jake.rmRf('out');
-  exec('./node_modules/.bin/jsdoc --verbose -c jsdoc.json lib/* docs/jsdoc/*');
+  var epath = path.join('./node_modules/.bin/jsdoc');
+  exec(epath+' --verbose -c jsdoc.json lib/* docs/jsdoc/*');
   console.log('Documentation generated in ./out.');
 });
 
 desc('Generates the EJS API docs for the public and private API');
 task('devdoc', function () {
   jake.rmRf('out');
-  exec('./node_modules/.bin/jsdoc --verbose -p -c jsdoc.json lib/* docs/jsdoc/*');
+  var epath = path.join('./node_modules/.bin/jsdoc');
+  exec(epath+' --verbose -p -c jsdoc.json lib/* docs/jsdoc/*');
   console.log('Documentation generated in ./out.');
 });
 
@@ -51,13 +57,14 @@ desc('Publishes the EJS API docs');
 task('docPublish', ['doc'], function () {
   fs.writeFileSync('out/CNAME', 'api.ejs.co');
   console.log('Pushing docs to gh-pages...');
-  exec('./node_modules/.bin/git-directory-deploy --directory out/');
+  var epath = path.join('./node_modules/.bin/git-directory-deploy');
+  exec(epath+' --directory out/');
   console.log('Docs published to gh-pages.');
 });
 
 desc('Runs the EJS test suite');
 task('test', ['lint'], function () {
-  exec('./node_modules/.bin/mocha');
+  exec(path.join('./node_modules/.bin/mocha'));
 });
 
 publishTask('ejs', ['build'], function () {
diff --git a/node_modules/ejs/lib/ejs.js b/node_modules/ejs/lib/ejs.js
index aa6322e304ab6a9a63efeaaf301c792ade243d42..65590eaed0d7fdf600b08fdc51e90083f5960595 100644
--- a/node_modules/ejs/lib/ejs.js
+++ b/node_modules/ejs/lib/ejs.js
@@ -44,6 +44,7 @@
  * @public
  */
 
+
 var fs = require('fs');
 var path = require('path');
 var utils = require('./utils');
@@ -64,6 +65,7 @@ var _OPTS_PASSABLE_WITH_DATA = ['delimiter', 'scope', 'context', 'debug', 'compi
 // so we make an exception for `renderFile`
 var _OPTS_PASSABLE_WITH_DATA_EXPRESS = _OPTS_PASSABLE_WITH_DATA.concat('cache');
 var _BOM = /^\uFEFF/;
+var _JS_IDENTIFIER = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/;
 
 /**
  * EJS template function cache. This can be a LRU object from lru-cache NPM
@@ -305,7 +307,7 @@ function fileLoader(filePath){
  */
 
 function includeFile(path, options) {
-  var opts = utils.shallowCopy({}, options);
+  var opts = utils.shallowCopy(utils.createNullProtoObjWherePossible(), options);
   opts.filename = getIncludePath(path, opts);
   if (typeof options.includer === 'function') {
     var includerResult = options.includer(path, opts.filename);
@@ -411,8 +413,8 @@ exports.compile = function compile(template, opts) {
  */
 
 exports.render = function (template, d, o) {
-  var data = d || {};
-  var opts = o || {};
+  var data = d || utils.createNullProtoObjWherePossible();
+  var opts = o || utils.createNullProtoObjWherePossible();
 
   // No options object -- if there are optiony names
   // in the data, copy them to options
@@ -483,7 +485,7 @@ exports.renderFile = function () {
     opts.filename = filename;
   }
   else {
-    data = {};
+    data = utils.createNullProtoObjWherePossible();
   }
 
   return tryHandleCache(opts, data, cb);
@@ -505,8 +507,8 @@ exports.clearCache = function () {
 };
 
 function Template(text, opts) {
-  opts = opts || {};
-  var options = {};
+  opts = opts || utils.createNullProtoObjWherePossible();
+  var options = utils.createNullProtoObjWherePossible();
   this.templateText = text;
   /** @type {string | null} */
   this.mode = null;
@@ -587,12 +589,21 @@ Template.prototype = {
         '  var __output = "";\n' +
         '  function __append(s) { if (s !== undefined && s !== null) __output += s }\n';
       if (opts.outputFunctionName) {
+        if (!_JS_IDENTIFIER.test(opts.outputFunctionName)) {
+          throw new Error('outputFunctionName is not a valid JS identifier.');
+        }
         prepended += '  var ' + opts.outputFunctionName + ' = __append;' + '\n';
       }
+      if (opts.localsName && !_JS_IDENTIFIER.test(opts.localsName)) {
+        throw new Error('localsName is not a valid JS identifier.');
+      }
       if (opts.destructuredLocals && opts.destructuredLocals.length) {
         var destructuring = '  var __locals = (' + opts.localsName + ' || {}),\n';
         for (var i = 0; i < opts.destructuredLocals.length; i++) {
           var name = opts.destructuredLocals[i];
+          if (!_JS_IDENTIFIER.test(name)) {
+            throw new Error('destructuredLocals[' + i + '] is not a valid JS identifier.');
+          }
           if (i > 0) {
             destructuring += ',\n  ';
           }
@@ -683,13 +694,14 @@ Template.prototype = {
     // Adds a local `include` function which allows full recursive include
     var returnedFn = opts.client ? fn : function anonymous(data) {
       var include = function (path, includeData) {
-        var d = utils.shallowCopy({}, data);
+        var d = utils.shallowCopy(utils.createNullProtoObjWherePossible(), data);
         if (includeData) {
           d = utils.shallowCopy(d, includeData);
         }
         return includeFile(path, opts)(d);
       };
-      return fn.apply(opts.context, [data || {}, escapeFn, include, rethrow]);
+      return fn.apply(opts.context,
+        [data || utils.createNullProtoObjWherePossible(), escapeFn, include, rethrow]);
     };
     if (opts.filename && typeof Object.defineProperty === 'function') {
       var filename = opts.filename;
diff --git a/node_modules/ejs/lib/utils.js b/node_modules/ejs/lib/utils.js
index 284de06624d7a7fb85e1034f9e218c472d717ab8..a0434d58ab4317c8b195d3efb5cfebd0e276132e 100644
--- a/node_modules/ejs/lib/utils.js
+++ b/node_modules/ejs/lib/utils.js
@@ -25,6 +25,8 @@
 'use strict';
 
 var regExpChars = /[|\\{}()[\]^$+*?.]/g;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); };
 
 /**
  * Escape characters reserved in regular expressions.
@@ -97,9 +99,25 @@ exports.escapeXML = function (markup) {
     : String(markup)
       .replace(_MATCH_HTML, encode_char);
 };
-exports.escapeXML.toString = function () {
+
+function escapeXMLToString() {
   return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr;
-};
+}
+
+try {
+  if (typeof Object.defineProperty === 'function') {
+  // If the Function prototype is frozen, the "toString" property is non-writable. This means that any objects which inherit this property
+  // cannot have the property changed using an assignment. If using strict mode, attempting that will cause an error. If not using strict
+  // mode, attempting that will be silently ignored.
+  // However, we can still explicitly shadow the prototype's "toString" property by defining a new "toString" property on this object.
+    Object.defineProperty(exports.escapeXML, 'toString', { value: escapeXMLToString });
+  } else {
+    // If Object.defineProperty() doesn't exist, attempt to shadow this property using the assignment operator.
+    exports.escapeXML.toString = escapeXMLToString;
+  }
+} catch (err) {
+  console.warn('Unable to set escapeXML.toString (is the Function prototype frozen?)');
+}
 
 /**
  * Naive copy of properties from one object to another.
@@ -114,8 +132,16 @@ exports.escapeXML.toString = function () {
  */
 exports.shallowCopy = function (to, from) {
   from = from || {};
-  for (var p in from) {
-    to[p] = from[p];
+  if ((to !== null) && (to !== undefined)) {
+    for (var p in from) {
+      if (!hasOwn(from, p)) {
+        continue;
+      }
+      if (p === '__proto__' || p === 'constructor') {
+        continue;
+      }
+      to[p] = from[p];
+    }
   }
   return to;
 };
@@ -133,10 +159,20 @@ exports.shallowCopy = function (to, from) {
  * @private
  */
 exports.shallowCopyFromList = function (to, from, list) {
-  for (var i = 0; i < list.length; i++) {
-    var p = list[i];
-    if (typeof from[p] != 'undefined') {
-      to[p] = from[p];
+  list = list || [];
+  from = from || {};
+  if ((to !== null) && (to !== undefined)) {
+    for (var i = 0; i < list.length; i++) {
+      var p = list[i];
+      if (typeof from[p] != 'undefined') {
+        if (!hasOwn(from, p)) {
+          continue;
+        }
+        if (p === '__proto__' || p === 'constructor') {
+          continue;
+        }
+        to[p] = from[p];
+      }
     }
   }
   return to;
@@ -177,3 +213,29 @@ exports.cache = {
 exports.hyphenToCamel = function (str) {
   return str.replace(/-[a-z]/g, function (match) { return match[1].toUpperCase(); });
 };
+
+/**
+ * Returns a null-prototype object in runtimes that support it
+ *
+ * @return {Object} Object, prototype will be set to null where possible
+ * @static
+ * @private
+ */
+exports.createNullProtoObjWherePossible = (function () {
+  if (typeof Object.create == 'function') {
+    return function () {
+      return Object.create(null);
+    };
+  }
+  if (!({__proto__: null} instanceof Object)) {
+    return function () {
+      return {__proto__: null};
+    };
+  }
+  // Not possible, just pass through
+  return function () {
+    return {};
+  };
+})();
+
+
diff --git a/node_modules/ejs/package.json b/node_modules/ejs/package.json
index c2b036bead494246533e81248b92d2ea7151336c..a02fc08938efc52aa18f1972add2f900af986382 100644
--- a/node_modules/ejs/package.json
+++ b/node_modules/ejs/package.json
@@ -6,7 +6,7 @@
     "engine",
     "ejs"
   ],
-  "version": "3.1.6",
+  "version": "3.1.9",
   "author": "Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)",
   "license": "Apache-2.0",
   "bin": {
@@ -22,21 +22,21 @@
   "bugs": "https://github.com/mde/ejs/issues",
   "homepage": "https://github.com/mde/ejs",
   "dependencies": {
-    "jake": "^10.6.1"
+    "jake": "^10.8.5"
   },
   "devDependencies": {
     "browserify": "^16.5.1",
     "eslint": "^6.8.0",
     "git-directory-deploy": "^1.5.1",
-    "jsdoc": "^3.6.4",
+    "jsdoc": "^4.0.2",
     "lru-cache": "^4.0.1",
-    "mocha": "^7.1.1",
+    "mocha": "^10.2.0",
     "uglify-js": "^3.3.16"
   },
   "engines": {
     "node": ">=0.10.0"
   },
   "scripts": {
-    "test": "mocha"
+    "test": "mocha -u tdd"
   }
 }
diff --git a/node_modules/escape-string-regexp/index.js b/node_modules/escape-string-regexp/index.js
deleted file mode 100644
index 7834bf9b24c481efa379fc07679c2d8e3ba85247..0000000000000000000000000000000000000000
--- a/node_modules/escape-string-regexp/index.js
+++ /dev/null
@@ -1,11 +0,0 @@
-'use strict';
-
-var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
-
-module.exports = function (str) {
-	if (typeof str !== 'string') {
-		throw new TypeError('Expected a string');
-	}
-
-	return str.replace(matchOperatorsRe, '\\$&');
-};
diff --git a/node_modules/escape-string-regexp/package.json b/node_modules/escape-string-regexp/package.json
deleted file mode 100644
index f307df34a232c01007db4b221a3af9370f07b787..0000000000000000000000000000000000000000
--- a/node_modules/escape-string-regexp/package.json
+++ /dev/null
@@ -1,41 +0,0 @@
-{
-  "name": "escape-string-regexp",
-  "version": "1.0.5",
-  "description": "Escape RegExp special characters",
-  "license": "MIT",
-  "repository": "sindresorhus/escape-string-regexp",
-  "author": {
-    "name": "Sindre Sorhus",
-    "email": "sindresorhus@gmail.com",
-    "url": "sindresorhus.com"
-  },
-  "maintainers": [
-    "Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)",
-    "Joshua Boy Nicolai Appelman <joshua@jbna.nl> (jbna.nl)"
-  ],
-  "engines": {
-    "node": ">=0.8.0"
-  },
-  "scripts": {
-    "test": "xo && ava"
-  },
-  "files": [
-    "index.js"
-  ],
-  "keywords": [
-    "escape",
-    "regex",
-    "regexp",
-    "re",
-    "regular",
-    "expression",
-    "string",
-    "str",
-    "special",
-    "characters"
-  ],
-  "devDependencies": {
-    "ava": "*",
-    "xo": "*"
-  }
-}
diff --git a/node_modules/escape-string-regexp/readme.md b/node_modules/escape-string-regexp/readme.md
deleted file mode 100644
index 87ac82d5ef8bc9515f709cf0dffe4c7a6fb84f93..0000000000000000000000000000000000000000
--- a/node_modules/escape-string-regexp/readme.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# escape-string-regexp [![Build Status](https://travis-ci.org/sindresorhus/escape-string-regexp.svg?branch=master)](https://travis-ci.org/sindresorhus/escape-string-regexp)
-
-> Escape RegExp special characters
-
-
-## Install
-
-```
-$ npm install --save escape-string-regexp
-```
-
-
-## Usage
-
-```js
-const escapeStringRegexp = require('escape-string-regexp');
-
-const escapedString = escapeStringRegexp('how much $ for a unicorn?');
-//=> 'how much \$ for a unicorn\?'
-
-new RegExp(escapedString);
-```
-
-
-## License
-
-MIT © [Sindre Sorhus](http://sindresorhus.com)
diff --git a/node_modules/filelist/index.d.ts b/node_modules/filelist/index.d.ts
index dbf6dc5d416d1168e709454fc8364b013c649d2e..a6addf28ca0b05e613a4ee0c34adf4131ed3b46b 100644
--- a/node_modules/filelist/index.d.ts
+++ b/node_modules/filelist/index.d.ts
@@ -1,54 +1,110 @@
-// Type definitions for filelist v0.0.6
-// Project: https://github.com/mde/filelist
-// Definitions by: Christophe MASSOLIN <https://github.com/FuriouZz>
-// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
-
-declare module "filelist" {
-  export class FileList {
-    pendingAdd: string[]
-    pending: boolean
-    excludes: {
-      pats: RegExp[],
-      funcs: Function[],
-      regex: null | RegExp
-    }
-    items: string[]
-    static clone(): FileList
-    static verbose: boolean
-    toArray(): string[]
-    include(options: any, ...items: string[]): void
-    exclude(...items: string[]): void
-    resolve(): void
-    clearInclusions(): void
-    clearExclusions(): void
-    length(): number
-    toString(): string;
-    toLocaleString(): string;
-    push(...items: string[]): number;
-    pop(): string | undefined;
-    concat(...items: ReadonlyArray<string>[]): string[];
-    concat(...items: (string | ReadonlyArray<string>)[]): string[];
-    join(separator?: string): string;
-    reverse(): string[];
-    shift(): string | undefined;
-    slice(start?: number, end?: number): string[];
-    sort(compareFn?: (a: string, b: string) => number): this;
-    splice(start: number, deleteCount?: number): string[];
-    splice(start: number, deleteCount: number, ...items: string[]): string[];
-    unshift(...items: string[]): number;
-    indexOf(searchElement: string, fromIndex?: number): number;
-    lastIndexOf(searchElement: string, fromIndex?: number): number;
-    every(callbackfn: (value: string, index: number, array: string[]) => boolean, thisArg?: any): boolean;
-    some(callbackfn: (value: string, index: number, array: string[]) => boolean, thisArg?: any): boolean;
-    forEach(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void;
-    map<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any): U[];
-    filter<S extends string>(callbackfn: (value: string, index: number, array: string[]) => value is S, thisArg?: any): S[];
-    filter(callbackfn: (value: string, index: number, array: string[]) => any, thisArg?: any): string[];
-    reduce(callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string;
-    reduce(callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string;
-    reduce<U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U;
-    reduceRight(callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string;
-    reduceRight(callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string;
-    reduceRight<U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U;
+// IncludeOptions definitions copied from minimatch (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/minimatch/index.d.ts)
+interface IncludeOptions {
+  /**
+   * Dump a ton of stuff to stderr.
+   *
+   * @default false
+   */
+  debug?: boolean;
+
+  /**
+   * Do not expand {a,b} and {1..3} brace sets.
+   *
+   * @default false
+   */
+  nobrace?: boolean;
+
+  /**
+   * Disable ** matching against multiple folder names.
+   *
+   * @default false
+   */
+  noglobstar?: boolean;
+
+  /**
+   * Allow patterns to match filenames starting with a period,
+   * even if the pattern does not explicitly have a period in that spot.
+   *
+   * @default false
+   */
+  dot?: boolean;
+
+  /**
+   * Disable "extglob" style patterns like +(a|b).
+   *
+   * @default false
+   */
+  noext?: boolean;
+
+  /**
+   * Perform a case-insensitive match.
+   *
+   * @default false
+   */
+  nocase?: boolean;
+
+  /**
+   * When a match is not found by minimatch.match,
+   * return a list containing the pattern itself if this option is set.
+   * Otherwise, an empty list is returned if there are no matches.
+   *
+   * @default false
+   */
+  nonull?: boolean;
+
+  /**
+   * If set, then patterns without slashes will be matched against
+   * the basename of the path if it contains slashes.
+   *
+   * @default false
+   */
+  matchBase?: boolean;
+
+  /**
+   * Suppress the behavior of treating #
+   * at the start of a pattern as a comment.
+   *
+   * @default false
+   */
+  nocomment?: boolean;
+
+  /**
+   * Suppress the behavior of treating a leading ! character as negation.
+   *
+   * @default false
+   */
+  nonegate?: boolean;
+
+  /**
+   * Returns from negate expressions the same as if they were not negated.
+   * (Ie, true on a hit, false on a miss.)
+   *
+   * @default false
+   */
+  flipNegate?: boolean;
+}
+
+export class FileList {
+  static clone(): FileList
+  static verbose: boolean
+}
+
+export interface FileList extends Omit<Array<string>, "length"> {
+  pendingAdd: string[]
+  pending: boolean
+  excludes: {
+    pats: RegExp[],
+    funcs: Function[],
+    regex: null | RegExp
   }
+  items: string[]
+  toArray(): string[]
+  include(...items: string[]): this
+  include(...items: (IncludeOptions | string)[]): this
+  exclude(...items: string[]): this
+  shouldExclude(item: string): boolean
+  resolve(): this
+  clearInclusions(): this
+  clearExclusions(): this
+  length(): number
 }
\ No newline at end of file
diff --git a/node_modules/filelist/index.js b/node_modules/filelist/index.js
index fef873a541e969ee2258b88af6f0e028894c3fe8..34ca389745f6b1548d2f4a8102aa6bf0fc843eab 100644
--- a/node_modules/filelist/index.js
+++ b/node_modules/filelist/index.js
@@ -24,6 +24,8 @@ var fs = require('fs')
 , _readDir
 , readdirR
 , globSync;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var hasOwn = function (obj, key) { return hasOwnProperty.apply(obj, [key]); };
 
   /**
     @name escapeRegExpChars
@@ -59,8 +61,15 @@ var fs = require('fs')
       , key, value;
 
     for (key in otherObj) {
-      value = otherObj[key];
 
+      if (!hasOwn(otherObj, key)) {
+        continue;
+      }
+      if (key === '__proto__' || key === 'constructor') {
+        continue;
+      }
+
+      value = otherObj[key];
       // Check if a value is an Object, if so recursively add it's key/values
       if (typeof value === 'object' && !(value instanceof Array)) {
         // Update value of object to the one from otherObj
diff --git a/node_modules/filelist/node_modules/brace-expansion/.github/FUNDING.yml b/node_modules/filelist/node_modules/brace-expansion/.github/FUNDING.yml
new file mode 100644
index 0000000000000000000000000000000000000000..79d1eafceccdfd94e9da95af5ccc8ccce24f198b
--- /dev/null
+++ b/node_modules/filelist/node_modules/brace-expansion/.github/FUNDING.yml
@@ -0,0 +1,2 @@
+tidelift: "npm/brace-expansion"
+patreon: juliangruber
diff --git a/node_modules/filelist/node_modules/brace-expansion/LICENSE b/node_modules/filelist/node_modules/brace-expansion/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..de3226673c3874b1c6506db022393c753495655c
--- /dev/null
+++ b/node_modules/filelist/node_modules/brace-expansion/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/filelist/node_modules/brace-expansion/README.md b/node_modules/filelist/node_modules/brace-expansion/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..e55c583dd095a596ed084669bce5860315ec7919
--- /dev/null
+++ b/node_modules/filelist/node_modules/brace-expansion/README.md
@@ -0,0 +1,135 @@
+# brace-expansion
+
+[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html), 
+as known from sh/bash, in JavaScript.
+
+[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion)
+[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion)
+[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/)
+
+[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion)
+
+## Example
+
+```js
+var expand = require('brace-expansion');
+
+expand('file-{a,b,c}.jpg')
+// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
+
+expand('-v{,,}')
+// => ['-v', '-v', '-v']
+
+expand('file{0..2}.jpg')
+// => ['file0.jpg', 'file1.jpg', 'file2.jpg']
+
+expand('file-{a..c}.jpg')
+// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
+
+expand('file{2..0}.jpg')
+// => ['file2.jpg', 'file1.jpg', 'file0.jpg']
+
+expand('file{0..4..2}.jpg')
+// => ['file0.jpg', 'file2.jpg', 'file4.jpg']
+
+expand('file-{a..e..2}.jpg')
+// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
+
+expand('file{00..10..5}.jpg')
+// => ['file00.jpg', 'file05.jpg', 'file10.jpg']
+
+expand('{{A..C},{a..c}}')
+// => ['A', 'B', 'C', 'a', 'b', 'c']
+
+expand('ppp{,config,oe{,conf}}')
+// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
+```
+
+## API
+
+```js
+var expand = require('brace-expansion');
+```
+
+### var expanded = expand(str)
+
+Return an array of all possible and valid expansions of `str`. If none are
+found, `[str]` is returned.
+
+Valid expansions are:
+
+```js
+/^(.*,)+(.+)?$/
+// {a,b,...}
+```
+
+A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
+
+```js
+/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
+// {x..y[..incr]}
+```
+
+A numeric sequence from `x` to `y` inclusive, with optional increment.
+If `x` or `y` start with a leading `0`, all the numbers will be padded
+to have equal length. Negative numbers and backwards iteration work too.
+
+```js
+/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
+// {x..y[..incr]}
+```
+
+An alphabetic sequence from `x` to `y` inclusive, with optional increment.
+`x` and `y` must be exactly one character, and if given, `incr` must be a
+number.
+
+For compatibility reasons, the string `${` is not eligible for brace expansion.
+
+## Installation
+
+With [npm](https://npmjs.org) do:
+
+```bash
+npm install brace-expansion
+```
+
+## Contributors
+
+- [Julian Gruber](https://github.com/juliangruber)
+- [Isaac Z. Schlueter](https://github.com/isaacs)
+
+## Sponsors
+
+This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
+
+Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!
+
+## Security contact information
+
+To report a security vulnerability, please use the
+[Tidelift security contact](https://tidelift.com/security).
+Tidelift will coordinate the fix and disclosure.
+
+## License
+
+(MIT)
+
+Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/filelist/node_modules/brace-expansion/index.js b/node_modules/filelist/node_modules/brace-expansion/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..4af9ddee463f4ac5eeda365926af401b6ce85481
--- /dev/null
+++ b/node_modules/filelist/node_modules/brace-expansion/index.js
@@ -0,0 +1,203 @@
+var balanced = require('balanced-match');
+
+module.exports = expandTop;
+
+var escSlash = '\0SLASH'+Math.random()+'\0';
+var escOpen = '\0OPEN'+Math.random()+'\0';
+var escClose = '\0CLOSE'+Math.random()+'\0';
+var escComma = '\0COMMA'+Math.random()+'\0';
+var escPeriod = '\0PERIOD'+Math.random()+'\0';
+
+function numeric(str) {
+  return parseInt(str, 10) == str
+    ? parseInt(str, 10)
+    : str.charCodeAt(0);
+}
+
+function escapeBraces(str) {
+  return str.split('\\\\').join(escSlash)
+            .split('\\{').join(escOpen)
+            .split('\\}').join(escClose)
+            .split('\\,').join(escComma)
+            .split('\\.').join(escPeriod);
+}
+
+function unescapeBraces(str) {
+  return str.split(escSlash).join('\\')
+            .split(escOpen).join('{')
+            .split(escClose).join('}')
+            .split(escComma).join(',')
+            .split(escPeriod).join('.');
+}
+
+
+// Basically just str.split(","), but handling cases
+// where we have nested braced sections, which should be
+// treated as individual members, like {a,{b,c},d}
+function parseCommaParts(str) {
+  if (!str)
+    return [''];
+
+  var parts = [];
+  var m = balanced('{', '}', str);
+
+  if (!m)
+    return str.split(',');
+
+  var pre = m.pre;
+  var body = m.body;
+  var post = m.post;
+  var p = pre.split(',');
+
+  p[p.length-1] += '{' + body + '}';
+  var postParts = parseCommaParts(post);
+  if (post.length) {
+    p[p.length-1] += postParts.shift();
+    p.push.apply(p, postParts);
+  }
+
+  parts.push.apply(parts, p);
+
+  return parts;
+}
+
+function expandTop(str) {
+  if (!str)
+    return [];
+
+  // I don't know why Bash 4.3 does this, but it does.
+  // Anything starting with {} will have the first two bytes preserved
+  // but *only* at the top level, so {},a}b will not expand to anything,
+  // but a{},b}c will be expanded to [a}c,abc].
+  // One could argue that this is a bug in Bash, but since the goal of
+  // this module is to match Bash's rules, we escape a leading {}
+  if (str.substr(0, 2) === '{}') {
+    str = '\\{\\}' + str.substr(2);
+  }
+
+  return expand(escapeBraces(str), true).map(unescapeBraces);
+}
+
+function embrace(str) {
+  return '{' + str + '}';
+}
+function isPadded(el) {
+  return /^-?0\d/.test(el);
+}
+
+function lte(i, y) {
+  return i <= y;
+}
+function gte(i, y) {
+  return i >= y;
+}
+
+function expand(str, isTop) {
+  var expansions = [];
+
+  var m = balanced('{', '}', str);
+  if (!m) return [str];
+
+  // no need to expand pre, since it is guaranteed to be free of brace-sets
+  var pre = m.pre;
+  var post = m.post.length
+    ? expand(m.post, false)
+    : [''];
+
+  if (/\$$/.test(m.pre)) {    
+    for (var k = 0; k < post.length; k++) {
+      var expansion = pre+ '{' + m.body + '}' + post[k];
+      expansions.push(expansion);
+    }
+  } else {
+    var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
+    var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
+    var isSequence = isNumericSequence || isAlphaSequence;
+    var isOptions = m.body.indexOf(',') >= 0;
+    if (!isSequence && !isOptions) {
+      // {a},b}
+      if (m.post.match(/,.*\}/)) {
+        str = m.pre + '{' + m.body + escClose + m.post;
+        return expand(str);
+      }
+      return [str];
+    }
+
+    var n;
+    if (isSequence) {
+      n = m.body.split(/\.\./);
+    } else {
+      n = parseCommaParts(m.body);
+      if (n.length === 1) {
+        // x{{a,b}}y ==> x{a}y x{b}y
+        n = expand(n[0], false).map(embrace);
+        if (n.length === 1) {
+          return post.map(function(p) {
+            return m.pre + n[0] + p;
+          });
+        }
+      }
+    }
+
+    // at this point, n is the parts, and we know it's not a comma set
+    // with a single entry.
+    var N;
+
+    if (isSequence) {
+      var x = numeric(n[0]);
+      var y = numeric(n[1]);
+      var width = Math.max(n[0].length, n[1].length)
+      var incr = n.length == 3
+        ? Math.abs(numeric(n[2]))
+        : 1;
+      var test = lte;
+      var reverse = y < x;
+      if (reverse) {
+        incr *= -1;
+        test = gte;
+      }
+      var pad = n.some(isPadded);
+
+      N = [];
+
+      for (var i = x; test(i, y); i += incr) {
+        var c;
+        if (isAlphaSequence) {
+          c = String.fromCharCode(i);
+          if (c === '\\')
+            c = '';
+        } else {
+          c = String(i);
+          if (pad) {
+            var need = width - c.length;
+            if (need > 0) {
+              var z = new Array(need + 1).join('0');
+              if (i < 0)
+                c = '-' + z + c.slice(1);
+              else
+                c = z + c;
+            }
+          }
+        }
+        N.push(c);
+      }
+    } else {
+      N = [];
+
+      for (var j = 0; j < n.length; j++) {
+        N.push.apply(N, expand(n[j], false));
+      }
+    }
+
+    for (var j = 0; j < N.length; j++) {
+      for (var k = 0; k < post.length; k++) {
+        var expansion = pre + N[j] + post[k];
+        if (!isTop || isSequence || expansion)
+          expansions.push(expansion);
+      }
+    }
+  }
+
+  return expansions;
+}
+
diff --git a/node_modules/filelist/node_modules/brace-expansion/package.json b/node_modules/filelist/node_modules/brace-expansion/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..7097d41e39de5df4544966717dc8c9de0871a5de
--- /dev/null
+++ b/node_modules/filelist/node_modules/brace-expansion/package.json
@@ -0,0 +1,46 @@
+{
+  "name": "brace-expansion",
+  "description": "Brace expansion as known from sh/bash",
+  "version": "2.0.1",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/juliangruber/brace-expansion.git"
+  },
+  "homepage": "https://github.com/juliangruber/brace-expansion",
+  "main": "index.js",
+  "scripts": {
+    "test": "tape test/*.js",
+    "gentest": "bash test/generate.sh",
+    "bench": "matcha test/perf/bench.js"
+  },
+  "dependencies": {
+    "balanced-match": "^1.0.0"
+  },
+  "devDependencies": {
+    "@c4312/matcha": "^1.3.1",
+    "tape": "^4.6.0"
+  },
+  "keywords": [],
+  "author": {
+    "name": "Julian Gruber",
+    "email": "mail@juliangruber.com",
+    "url": "http://juliangruber.com"
+  },
+  "license": "MIT",
+  "testling": {
+    "files": "test/*.js",
+    "browsers": [
+      "ie/8..latest",
+      "firefox/20..latest",
+      "firefox/nightly",
+      "chrome/25..latest",
+      "chrome/canary",
+      "opera/12..latest",
+      "opera/next",
+      "safari/5.1..latest",
+      "ipad/6.0..latest",
+      "iphone/6.0..latest",
+      "android-browser/4.2..latest"
+    ]
+  }
+}
diff --git a/node_modules/filelist/node_modules/minimatch/LICENSE b/node_modules/filelist/node_modules/minimatch/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..1493534e60dce4a4c73e60e0bb448a0ab2567c9d
--- /dev/null
+++ b/node_modules/filelist/node_modules/minimatch/LICENSE
@@ -0,0 +1,15 @@
+The ISC License
+
+Copyright (c) 2011-2023 Isaac Z. Schlueter and Contributors
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/node_modules/filelist/node_modules/minimatch/README.md b/node_modules/filelist/node_modules/minimatch/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a5bdefaa50e008706c43883c5a130f7b629e9a72
--- /dev/null
+++ b/node_modules/filelist/node_modules/minimatch/README.md
@@ -0,0 +1,259 @@
+# minimatch
+
+A minimal matching utility.
+
+[![Build Status](https://travis-ci.org/isaacs/minimatch.svg?branch=master)](http://travis-ci.org/isaacs/minimatch)
+
+
+This is the matching library used internally by npm.
+
+It works by converting glob expressions into JavaScript `RegExp`
+objects.
+
+## Usage
+
+```javascript
+var minimatch = require("minimatch")
+
+minimatch("bar.foo", "*.foo") // true!
+minimatch("bar.foo", "*.bar") // false!
+minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
+```
+
+## Features
+
+Supports these glob features:
+
+* Brace Expansion
+* Extended glob matching
+* "Globstar" `**` matching
+
+See:
+
+* `man sh`
+* `man bash`
+* `man 3 fnmatch`
+* `man 5 gitignore`
+
+## Windows
+
+**Please only use forward-slashes in glob expressions.**
+
+Though windows uses either `/` or `\` as its path separator, only `/`
+characters are used by this glob implementation.  You must use
+forward-slashes **only** in glob expressions.  Back-slashes in patterns
+will always be interpreted as escape characters, not path separators.
+
+Note that `\` or `/` _will_ be interpreted as path separators in paths on
+Windows, and will match against `/` in glob expressions.
+
+So just always use `/` in patterns.
+
+## Minimatch Class
+
+Create a minimatch object by instantiating the `minimatch.Minimatch` class.
+
+```javascript
+var Minimatch = require("minimatch").Minimatch
+var mm = new Minimatch(pattern, options)
+```
+
+### Properties
+
+* `pattern` The original pattern the minimatch object represents.
+* `options` The options supplied to the constructor.
+* `set` A 2-dimensional array of regexp or string expressions.
+  Each row in the
+  array corresponds to a brace-expanded pattern.  Each item in the row
+  corresponds to a single path-part.  For example, the pattern
+  `{a,b/c}/d` would expand to a set of patterns like:
+
+        [ [ a, d ]
+        , [ b, c, d ] ]
+
+    If a portion of the pattern doesn't have any "magic" in it
+    (that is, it's something like `"foo"` rather than `fo*o?`), then it
+    will be left as a string rather than converted to a regular
+    expression.
+
+* `regexp` Created by the `makeRe` method.  A single regular expression
+  expressing the entire pattern.  This is useful in cases where you wish
+  to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
+* `negate` True if the pattern is negated.
+* `comment` True if the pattern is a comment.
+* `empty` True if the pattern is `""`.
+
+### Methods
+
+* `makeRe` Generate the `regexp` member if necessary, and return it.
+  Will return `false` if the pattern is invalid.
+* `match(fname)` Return true if the filename matches the pattern, or
+  false otherwise.
+* `matchOne(fileArray, patternArray, partial)` Take a `/`-split
+  filename, and match it against a single row in the `regExpSet`.  This
+  method is mainly for internal use, but is exposed so that it can be
+  used by a glob-walker that needs to avoid excessive filesystem calls.
+
+All other methods are internal, and will be called as necessary.
+
+### minimatch(path, pattern, options)
+
+Main export.  Tests a path against the pattern using the options.
+
+```javascript
+var isJS = minimatch(file, "*.js", { matchBase: true })
+```
+
+### minimatch.filter(pattern, options)
+
+Returns a function that tests its
+supplied argument, suitable for use with `Array.filter`.  Example:
+
+```javascript
+var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
+```
+
+### minimatch.match(list, pattern, options)
+
+Match against the list of
+files, in the style of fnmatch or glob.  If nothing is matched, and
+options.nonull is set, then return a list containing the pattern itself.
+
+```javascript
+var javascripts = minimatch.match(fileList, "*.js", {matchBase: true})
+```
+
+### minimatch.makeRe(pattern, options)
+
+Make a regular expression object from the pattern.
+
+## Options
+
+All options are `false` by default.
+
+### debug
+
+Dump a ton of stuff to stderr.
+
+### nobrace
+
+Do not expand `{a,b}` and `{1..3}` brace sets.
+
+### noglobstar
+
+Disable `**` matching against multiple folder names.
+
+### dot
+
+Allow patterns to match filenames starting with a period, even if
+the pattern does not explicitly have a period in that spot.
+
+Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
+is set.
+
+### noext
+
+Disable "extglob" style patterns like `+(a|b)`.
+
+### nocase
+
+Perform a case-insensitive match.
+
+### nonull
+
+When a match is not found by `minimatch.match`, return a list containing
+the pattern itself if this option is set.  When not set, an empty list
+is returned if there are no matches.
+
+### matchBase
+
+If set, then patterns without slashes will be matched
+against the basename of the path if it contains slashes.  For example,
+`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
+
+### nocomment
+
+Suppress the behavior of treating `#` at the start of a pattern as a
+comment.
+
+### nonegate
+
+Suppress the behavior of treating a leading `!` character as negation.
+
+### flipNegate
+
+Returns from negate expressions the same as if they were not negated.
+(Ie, true on a hit, false on a miss.)
+
+### partial
+
+Compare a partial path to a pattern.  As long as the parts of the path that
+are present are not contradicted by the pattern, it will be treated as a
+match.  This is useful in applications where you're walking through a
+folder structure, and don't yet have the full path, but want to ensure that
+you do not walk down paths that can never be a match.
+
+For example,
+
+```js
+minimatch('/a/b', '/a/*/c/d', { partial: true })  // true, might be /a/b/c/d
+minimatch('/a/b', '/**/d', { partial: true })     // true, might be /a/b/.../d
+minimatch('/x/y/z', '/a/**/z', { partial: true }) // false, because x !== a
+```
+
+### windowsPathsNoEscape
+
+Use `\\` as a path separator _only_, and _never_ as an escape
+character.  If set, all `\\` characters are replaced with `/` in
+the pattern.  Note that this makes it **impossible** to match
+against paths containing literal glob pattern characters, but
+allows matching with patterns constructed using `path.join()` and
+`path.resolve()` on Windows platforms, mimicking the (buggy!)
+behavior of earlier versions on Windows.  Please use with
+caution, and be mindful of [the caveat about Windows
+paths](#windows).
+
+For legacy reasons, this is also set if
+`options.allowWindowsEscape` is set to the exact value `false`.
+
+## Comparisons to other fnmatch/glob implementations
+
+While strict compliance with the existing standards is a worthwhile
+goal, some discrepancies exist between minimatch and other
+implementations, and are intentional.
+
+If the pattern starts with a `!` character, then it is negated.  Set the
+`nonegate` flag to suppress this behavior, and treat leading `!`
+characters normally.  This is perhaps relevant if you wish to start the
+pattern with a negative extglob pattern like `!(a|B)`.  Multiple `!`
+characters at the start of a pattern will negate the pattern multiple
+times.
+
+If a pattern starts with `#`, then it is treated as a comment, and
+will not match anything.  Use `\#` to match a literal `#` at the
+start of a line, or set the `nocomment` flag to suppress this behavior.
+
+The double-star character `**` is supported by default, unless the
+`noglobstar` flag is set.  This is supported in the manner of bsdglob
+and bash 4.1, where `**` only has special significance if it is the only
+thing in a path part.  That is, `a/**/b` will match `a/x/y/b`, but
+`a/**b` will not.
+
+If an escaped pattern has no matches, and the `nonull` flag is set,
+then minimatch.match returns the pattern as-provided, rather than
+interpreting the character escapes.  For example,
+`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
+`"*a?"`.  This is akin to setting the `nullglob` option in bash, except
+that it does not resolve escaped pattern characters.
+
+If brace expansion is not disabled, then it is performed before any
+other interpretation of the glob pattern.  Thus, a pattern like
+`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
+**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
+checked for validity.  Since those two are valid, matching proceeds.
+
+Note that `fnmatch(3)` in libc is an extremely naive string comparison
+matcher, which does not do anything special for slashes.  This library is
+designed to be used in glob searching and file walkers, and so it does do
+special things with `/`.  Thus, `foo*` will not match `foo/bar` in this
+library, even though it would in `fnmatch(3)`.
diff --git a/node_modules/filelist/node_modules/minimatch/lib/path.js b/node_modules/filelist/node_modules/minimatch/lib/path.js
new file mode 100644
index 0000000000000000000000000000000000000000..ffe453d9e0557758c090f7053df5f426e172d84f
--- /dev/null
+++ b/node_modules/filelist/node_modules/minimatch/lib/path.js
@@ -0,0 +1,4 @@
+const isWindows = typeof process === 'object' &&
+  process &&
+  process.platform === 'win32'
+module.exports = isWindows ? { sep: '\\' } : { sep: '/' }
diff --git a/node_modules/filelist/node_modules/minimatch/minimatch.js b/node_modules/filelist/node_modules/minimatch/minimatch.js
new file mode 100644
index 0000000000000000000000000000000000000000..6c8bfc35181c6dff29f521e410d70e1a8db22505
--- /dev/null
+++ b/node_modules/filelist/node_modules/minimatch/minimatch.js
@@ -0,0 +1,944 @@
+const minimatch = module.exports = (p, pattern, options = {}) => {
+  assertValidPattern(pattern)
+
+  // shortcut: comments match nothing.
+  if (!options.nocomment && pattern.charAt(0) === '#') {
+    return false
+  }
+
+  return new Minimatch(pattern, options).match(p)
+}
+
+module.exports = minimatch
+
+const path = require('./lib/path.js')
+minimatch.sep = path.sep
+
+const GLOBSTAR = Symbol('globstar **')
+minimatch.GLOBSTAR = GLOBSTAR
+const expand = require('brace-expansion')
+
+const plTypes = {
+  '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
+  '?': { open: '(?:', close: ')?' },
+  '+': { open: '(?:', close: ')+' },
+  '*': { open: '(?:', close: ')*' },
+  '@': { open: '(?:', close: ')' }
+}
+
+// any single thing other than /
+// don't need to escape / when using new RegExp()
+const qmark = '[^/]'
+
+// * => any number of characters
+const star = qmark + '*?'
+
+// ** when dots are allowed.  Anything goes, except .. and .
+// not (^ or / followed by one or two dots followed by $ or /),
+// followed by anything, any number of times.
+const twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
+
+// not a ^ or / followed by a dot,
+// followed by anything, any number of times.
+const twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
+
+// "abc" -> { a:true, b:true, c:true }
+const charSet = s => s.split('').reduce((set, c) => {
+  set[c] = true
+  return set
+}, {})
+
+// characters that need to be escaped in RegExp.
+const reSpecials = charSet('().*{}+?[]^$\\!')
+
+// characters that indicate we have to add the pattern start
+const addPatternStartSet = charSet('[.(')
+
+// normalizes slashes.
+const slashSplit = /\/+/
+
+minimatch.filter = (pattern, options = {}) =>
+  (p, i, list) => minimatch(p, pattern, options)
+
+const ext = (a, b = {}) => {
+  const t = {}
+  Object.keys(a).forEach(k => t[k] = a[k])
+  Object.keys(b).forEach(k => t[k] = b[k])
+  return t
+}
+
+minimatch.defaults = def => {
+  if (!def || typeof def !== 'object' || !Object.keys(def).length) {
+    return minimatch
+  }
+
+  const orig = minimatch
+
+  const m = (p, pattern, options) => orig(p, pattern, ext(def, options))
+  m.Minimatch = class Minimatch extends orig.Minimatch {
+    constructor (pattern, options) {
+      super(pattern, ext(def, options))
+    }
+  }
+  m.Minimatch.defaults = options => orig.defaults(ext(def, options)).Minimatch
+  m.filter = (pattern, options) => orig.filter(pattern, ext(def, options))
+  m.defaults = options => orig.defaults(ext(def, options))
+  m.makeRe = (pattern, options) => orig.makeRe(pattern, ext(def, options))
+  m.braceExpand = (pattern, options) => orig.braceExpand(pattern, ext(def, options))
+  m.match = (list, pattern, options) => orig.match(list, pattern, ext(def, options))
+
+  return m
+}
+
+
+
+
+
+// Brace expansion:
+// a{b,c}d -> abd acd
+// a{b,}c -> abc ac
+// a{0..3}d -> a0d a1d a2d a3d
+// a{b,c{d,e}f}g -> abg acdfg acefg
+// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
+//
+// Invalid sets are not expanded.
+// a{2..}b -> a{2..}b
+// a{b}c -> a{b}c
+minimatch.braceExpand = (pattern, options) => braceExpand(pattern, options)
+
+const braceExpand = (pattern, options = {}) => {
+  assertValidPattern(pattern)
+
+  // Thanks to Yeting Li <https://github.com/yetingli> for
+  // improving this regexp to avoid a ReDOS vulnerability.
+  if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
+    // shortcut. no need to expand.
+    return [pattern]
+  }
+
+  return expand(pattern)
+}
+
+const MAX_PATTERN_LENGTH = 1024 * 64
+const assertValidPattern = pattern => {
+  if (typeof pattern !== 'string') {
+    throw new TypeError('invalid pattern')
+  }
+
+  if (pattern.length > MAX_PATTERN_LENGTH) {
+    throw new TypeError('pattern is too long')
+  }
+}
+
+// parse a component of the expanded set.
+// At this point, no pattern may contain "/" in it
+// so we're going to return a 2d array, where each entry is the full
+// pattern, split on '/', and then turned into a regular expression.
+// A regexp is made at the end which joins each array with an
+// escaped /, and another full one which joins each regexp with |.
+//
+// Following the lead of Bash 4.1, note that "**" only has special meaning
+// when it is the *only* thing in a path portion.  Otherwise, any series
+// of * is equivalent to a single *.  Globstar behavior is enabled by
+// default, and can be disabled by setting options.noglobstar.
+const SUBPARSE = Symbol('subparse')
+
+minimatch.makeRe = (pattern, options) =>
+  new Minimatch(pattern, options || {}).makeRe()
+
+minimatch.match = (list, pattern, options = {}) => {
+  const mm = new Minimatch(pattern, options)
+  list = list.filter(f => mm.match(f))
+  if (mm.options.nonull && !list.length) {
+    list.push(pattern)
+  }
+  return list
+}
+
+// replace stuff like \* with *
+const globUnescape = s => s.replace(/\\(.)/g, '$1')
+const charUnescape = s => s.replace(/\\([^-\]])/g, '$1')
+const regExpEscape = s => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
+const braExpEscape = s => s.replace(/[[\]\\]/g, '\\$&')
+
+class Minimatch {
+  constructor (pattern, options) {
+    assertValidPattern(pattern)
+
+    if (!options) options = {}
+
+    this.options = options
+    this.set = []
+    this.pattern = pattern
+    this.windowsPathsNoEscape = !!options.windowsPathsNoEscape ||
+      options.allowWindowsEscape === false
+    if (this.windowsPathsNoEscape) {
+      this.pattern = this.pattern.replace(/\\/g, '/')
+    }
+    this.regexp = null
+    this.negate = false
+    this.comment = false
+    this.empty = false
+    this.partial = !!options.partial
+
+    // make the set of regexps etc.
+    this.make()
+  }
+
+  debug () {}
+
+  make () {
+    const pattern = this.pattern
+    const options = this.options
+
+    // empty patterns and comments match nothing.
+    if (!options.nocomment && pattern.charAt(0) === '#') {
+      this.comment = true
+      return
+    }
+    if (!pattern) {
+      this.empty = true
+      return
+    }
+
+    // step 1: figure out negation, etc.
+    this.parseNegate()
+
+    // step 2: expand braces
+    let set = this.globSet = this.braceExpand()
+
+    if (options.debug) this.debug = (...args) => console.error(...args)
+
+    this.debug(this.pattern, set)
+
+    // step 3: now we have a set, so turn each one into a series of path-portion
+    // matching patterns.
+    // These will be regexps, except in the case of "**", which is
+    // set to the GLOBSTAR object for globstar behavior,
+    // and will not contain any / characters
+    set = this.globParts = set.map(s => s.split(slashSplit))
+
+    this.debug(this.pattern, set)
+
+    // glob --> regexps
+    set = set.map((s, si, set) => s.map(this.parse, this))
+
+    this.debug(this.pattern, set)
+
+    // filter out everything that didn't compile properly.
+    set = set.filter(s => s.indexOf(false) === -1)
+
+    this.debug(this.pattern, set)
+
+    this.set = set
+  }
+
+  parseNegate () {
+    if (this.options.nonegate) return
+
+    const pattern = this.pattern
+    let negate = false
+    let negateOffset = 0
+
+    for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
+      negate = !negate
+      negateOffset++
+    }
+
+    if (negateOffset) this.pattern = pattern.slice(negateOffset)
+    this.negate = negate
+  }
+
+  // set partial to true to test if, for example,
+  // "/a/b" matches the start of "/*/b/*/d"
+  // Partial means, if you run out of file before you run
+  // out of pattern, then that's fine, as long as all
+  // the parts match.
+  matchOne (file, pattern, partial) {
+    var options = this.options
+
+    this.debug('matchOne',
+      { 'this': this, file: file, pattern: pattern })
+
+    this.debug('matchOne', file.length, pattern.length)
+
+    for (var fi = 0,
+        pi = 0,
+        fl = file.length,
+        pl = pattern.length
+        ; (fi < fl) && (pi < pl)
+        ; fi++, pi++) {
+      this.debug('matchOne loop')
+      var p = pattern[pi]
+      var f = file[fi]
+
+      this.debug(pattern, p, f)
+
+      // should be impossible.
+      // some invalid regexp stuff in the set.
+      /* istanbul ignore if */
+      if (p === false) return false
+
+      if (p === GLOBSTAR) {
+        this.debug('GLOBSTAR', [pattern, p, f])
+
+        // "**"
+        // a/**/b/**/c would match the following:
+        // a/b/x/y/z/c
+        // a/x/y/z/b/c
+        // a/b/x/b/x/c
+        // a/b/c
+        // To do this, take the rest of the pattern after
+        // the **, and see if it would match the file remainder.
+        // If so, return success.
+        // If not, the ** "swallows" a segment, and try again.
+        // This is recursively awful.
+        //
+        // a/**/b/**/c matching a/b/x/y/z/c
+        // - a matches a
+        // - doublestar
+        //   - matchOne(b/x/y/z/c, b/**/c)
+        //     - b matches b
+        //     - doublestar
+        //       - matchOne(x/y/z/c, c) -> no
+        //       - matchOne(y/z/c, c) -> no
+        //       - matchOne(z/c, c) -> no
+        //       - matchOne(c, c) yes, hit
+        var fr = fi
+        var pr = pi + 1
+        if (pr === pl) {
+          this.debug('** at the end')
+          // a ** at the end will just swallow the rest.
+          // We have found a match.
+          // however, it will not swallow /.x, unless
+          // options.dot is set.
+          // . and .. are *never* matched by **, for explosively
+          // exponential reasons.
+          for (; fi < fl; fi++) {
+            if (file[fi] === '.' || file[fi] === '..' ||
+              (!options.dot && file[fi].charAt(0) === '.')) return false
+          }
+          return true
+        }
+
+        // ok, let's see if we can swallow whatever we can.
+        while (fr < fl) {
+          var swallowee = file[fr]
+
+          this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
+
+          // XXX remove this slice.  Just pass the start index.
+          if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
+            this.debug('globstar found match!', fr, fl, swallowee)
+            // found a match.
+            return true
+          } else {
+            // can't swallow "." or ".." ever.
+            // can only swallow ".foo" when explicitly asked.
+            if (swallowee === '.' || swallowee === '..' ||
+              (!options.dot && swallowee.charAt(0) === '.')) {
+              this.debug('dot detected!', file, fr, pattern, pr)
+              break
+            }
+
+            // ** swallows a segment, and continue.
+            this.debug('globstar swallow a segment, and continue')
+            fr++
+          }
+        }
+
+        // no match was found.
+        // However, in partial mode, we can't say this is necessarily over.
+        // If there's more *pattern* left, then
+        /* istanbul ignore if */
+        if (partial) {
+          // ran out of file
+          this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
+          if (fr === fl) return true
+        }
+        return false
+      }
+
+      // something other than **
+      // non-magic patterns just have to match exactly
+      // patterns with magic have been turned into regexps.
+      var hit
+      if (typeof p === 'string') {
+        hit = f === p
+        this.debug('string match', p, f, hit)
+      } else {
+        hit = f.match(p)
+        this.debug('pattern match', p, f, hit)
+      }
+
+      if (!hit) return false
+    }
+
+    // Note: ending in / means that we'll get a final ""
+    // at the end of the pattern.  This can only match a
+    // corresponding "" at the end of the file.
+    // If the file ends in /, then it can only match a
+    // a pattern that ends in /, unless the pattern just
+    // doesn't have any more for it. But, a/b/ should *not*
+    // match "a/b/*", even though "" matches against the
+    // [^/]*? pattern, except in partial mode, where it might
+    // simply not be reached yet.
+    // However, a/b/ should still satisfy a/*
+
+    // now either we fell off the end of the pattern, or we're done.
+    if (fi === fl && pi === pl) {
+      // ran out of pattern and filename at the same time.
+      // an exact hit!
+      return true
+    } else if (fi === fl) {
+      // ran out of file, but still had pattern left.
+      // this is ok if we're doing the match as part of
+      // a glob fs traversal.
+      return partial
+    } else /* istanbul ignore else */ if (pi === pl) {
+      // ran out of pattern, still have file left.
+      // this is only acceptable if we're on the very last
+      // empty segment of a file with a trailing slash.
+      // a/* should match a/b/
+      return (fi === fl - 1) && (file[fi] === '')
+    }
+
+    // should be unreachable.
+    /* istanbul ignore next */
+    throw new Error('wtf?')
+  }
+
+  braceExpand () {
+    return braceExpand(this.pattern, this.options)
+  }
+
+  parse (pattern, isSub) {
+    assertValidPattern(pattern)
+
+    const options = this.options
+
+    // shortcuts
+    if (pattern === '**') {
+      if (!options.noglobstar)
+        return GLOBSTAR
+      else
+        pattern = '*'
+    }
+    if (pattern === '') return ''
+
+    let re = ''
+    let hasMagic = false
+    let escaping = false
+    // ? => one single character
+    const patternListStack = []
+    const negativeLists = []
+    let stateChar
+    let inClass = false
+    let reClassStart = -1
+    let classStart = -1
+    let cs
+    let pl
+    let sp
+    // . and .. never match anything that doesn't start with .,
+    // even when options.dot is set.  However, if the pattern
+    // starts with ., then traversal patterns can match.
+    let dotTravAllowed = pattern.charAt(0) === '.'
+    let dotFileAllowed = options.dot || dotTravAllowed
+    const patternStart = () =>
+      dotTravAllowed
+        ? ''
+        : dotFileAllowed
+        ? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
+        : '(?!\\.)'
+    const subPatternStart = (p) =>
+      p.charAt(0) === '.'
+        ? ''
+        : options.dot
+        ? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
+        : '(?!\\.)'
+
+
+    const clearStateChar = () => {
+      if (stateChar) {
+        // we had some state-tracking character
+        // that wasn't consumed by this pass.
+        switch (stateChar) {
+          case '*':
+            re += star
+            hasMagic = true
+          break
+          case '?':
+            re += qmark
+            hasMagic = true
+          break
+          default:
+            re += '\\' + stateChar
+          break
+        }
+        this.debug('clearStateChar %j %j', stateChar, re)
+        stateChar = false
+      }
+    }
+
+    for (let i = 0, c; (i < pattern.length) && (c = pattern.charAt(i)); i++) {
+      this.debug('%s\t%s %s %j', pattern, i, re, c)
+
+      // skip over any that are escaped.
+      if (escaping) {
+        /* istanbul ignore next - completely not allowed, even escaped. */
+        if (c === '/') {
+          return false
+        }
+
+        if (reSpecials[c]) {
+          re += '\\'
+        }
+        re += c
+        escaping = false
+        continue
+      }
+
+      switch (c) {
+        /* istanbul ignore next */
+        case '/': {
+          // Should already be path-split by now.
+          return false
+        }
+
+        case '\\':
+          if (inClass && pattern.charAt(i + 1) === '-') {
+            re += c
+            continue
+          }
+
+          clearStateChar()
+          escaping = true
+        continue
+
+        // the various stateChar values
+        // for the "extglob" stuff.
+        case '?':
+        case '*':
+        case '+':
+        case '@':
+        case '!':
+          this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
+
+          // all of those are literals inside a class, except that
+          // the glob [!a] means [^a] in regexp
+          if (inClass) {
+            this.debug('  in class')
+            if (c === '!' && i === classStart + 1) c = '^'
+            re += c
+            continue
+          }
+
+          // if we already have a stateChar, then it means
+          // that there was something like ** or +? in there.
+          // Handle the stateChar, then proceed with this one.
+          this.debug('call clearStateChar %j', stateChar)
+          clearStateChar()
+          stateChar = c
+          // if extglob is disabled, then +(asdf|foo) isn't a thing.
+          // just clear the statechar *now*, rather than even diving into
+          // the patternList stuff.
+          if (options.noext) clearStateChar()
+        continue
+
+        case '(': {
+          if (inClass) {
+            re += '('
+            continue
+          }
+
+          if (!stateChar) {
+            re += '\\('
+            continue
+          }
+
+          const plEntry = {
+            type: stateChar,
+            start: i - 1,
+            reStart: re.length,
+            open: plTypes[stateChar].open,
+            close: plTypes[stateChar].close,
+          }
+          this.debug(this.pattern, '\t', plEntry)
+          patternListStack.push(plEntry)
+          // negation is (?:(?!(?:js)(?:<rest>))[^/]*)
+          re += plEntry.open
+          // next entry starts with a dot maybe?
+          if (plEntry.start === 0 && plEntry.type !== '!') {
+            dotTravAllowed = true
+            re += subPatternStart(pattern.slice(i + 1))
+          }
+          this.debug('plType %j %j', stateChar, re)
+          stateChar = false
+          continue
+        }
+
+        case ')': {
+          const plEntry = patternListStack[patternListStack.length - 1]
+          if (inClass || !plEntry) {
+            re += '\\)'
+            continue
+          }
+          patternListStack.pop()
+
+          // closing an extglob
+          clearStateChar()
+          hasMagic = true
+          pl = plEntry
+          // negation is (?:(?!js)[^/]*)
+          // The others are (?:<pattern>)<type>
+          re += pl.close
+          if (pl.type === '!') {
+            negativeLists.push(Object.assign(pl, { reEnd: re.length }))
+          }
+          continue
+        }
+
+        case '|': {
+          const plEntry = patternListStack[patternListStack.length - 1]
+          if (inClass || !plEntry) {
+            re += '\\|'
+            continue
+          }
+
+          clearStateChar()
+          re += '|'
+          // next subpattern can start with a dot?
+          if (plEntry.start === 0 && plEntry.type !== '!') {
+            dotTravAllowed = true
+            re += subPatternStart(pattern.slice(i + 1))
+          }
+          continue
+        }
+
+        // these are mostly the same in regexp and glob
+        case '[':
+          // swallow any state-tracking char before the [
+          clearStateChar()
+
+          if (inClass) {
+            re += '\\' + c
+            continue
+          }
+
+          inClass = true
+          classStart = i
+          reClassStart = re.length
+          re += c
+        continue
+
+        case ']':
+          //  a right bracket shall lose its special
+          //  meaning and represent itself in
+          //  a bracket expression if it occurs
+          //  first in the list.  -- POSIX.2 2.8.3.2
+          if (i === classStart + 1 || !inClass) {
+            re += '\\' + c
+            continue
+          }
+
+          // split where the last [ was, make sure we don't have
+          // an invalid re. if so, re-walk the contents of the
+          // would-be class to re-translate any characters that
+          // were passed through as-is
+          // TODO: It would probably be faster to determine this
+          // without a try/catch and a new RegExp, but it's tricky
+          // to do safely.  For now, this is safe and works.
+          cs = pattern.substring(classStart + 1, i)
+          try {
+            RegExp('[' + braExpEscape(charUnescape(cs)) + ']')
+            // looks good, finish up the class.
+            re += c
+          } catch (er) {
+            // out of order ranges in JS are errors, but in glob syntax,
+            // they're just a range that matches nothing.
+            re = re.substring(0, reClassStart) + '(?:$.)' // match nothing ever
+          }
+          hasMagic = true
+          inClass = false
+        continue
+
+        default:
+          // swallow any state char that wasn't consumed
+          clearStateChar()
+
+          if (reSpecials[c] && !(c === '^' && inClass)) {
+            re += '\\'
+          }
+
+          re += c
+          break
+
+      } // switch
+    } // for
+
+    // handle the case where we left a class open.
+    // "[abc" is valid, equivalent to "\[abc"
+    if (inClass) {
+      // split where the last [ was, and escape it
+      // this is a huge pita.  We now have to re-walk
+      // the contents of the would-be class to re-translate
+      // any characters that were passed through as-is
+      cs = pattern.slice(classStart + 1)
+      sp = this.parse(cs, SUBPARSE)
+      re = re.substring(0, reClassStart) + '\\[' + sp[0]
+      hasMagic = hasMagic || sp[1]
+    }
+
+    // handle the case where we had a +( thing at the *end*
+    // of the pattern.
+    // each pattern list stack adds 3 chars, and we need to go through
+    // and escape any | chars that were passed through as-is for the regexp.
+    // Go through and escape them, taking care not to double-escape any
+    // | chars that were already escaped.
+    for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
+      let tail
+      tail = re.slice(pl.reStart + pl.open.length)
+      this.debug('setting tail', re, pl)
+      // maybe some even number of \, then maybe 1 \, followed by a |
+      tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
+        /* istanbul ignore else - should already be done */
+        if (!$2) {
+          // the | isn't already escaped, so escape it.
+          $2 = '\\'
+        }
+
+        // need to escape all those slashes *again*, without escaping the
+        // one that we need for escaping the | character.  As it works out,
+        // escaping an even number of slashes can be done by simply repeating
+        // it exactly after itself.  That's why this trick works.
+        //
+        // I am sorry that you have to see this.
+        return $1 + $1 + $2 + '|'
+      })
+
+      this.debug('tail=%j\n   %s', tail, tail, pl, re)
+      const t = pl.type === '*' ? star
+        : pl.type === '?' ? qmark
+        : '\\' + pl.type
+
+      hasMagic = true
+      re = re.slice(0, pl.reStart) + t + '\\(' + tail
+    }
+
+    // handle trailing things that only matter at the very end.
+    clearStateChar()
+    if (escaping) {
+      // trailing \\
+      re += '\\\\'
+    }
+
+    // only need to apply the nodot start if the re starts with
+    // something that could conceivably capture a dot
+    const addPatternStart = addPatternStartSet[re.charAt(0)]
+
+    // Hack to work around lack of negative lookbehind in JS
+    // A pattern like: *.!(x).!(y|z) needs to ensure that a name
+    // like 'a.xyz.yz' doesn't match.  So, the first negative
+    // lookahead, has to look ALL the way ahead, to the end of
+    // the pattern.
+    for (let n = negativeLists.length - 1; n > -1; n--) {
+      const nl = negativeLists[n]
+
+      const nlBefore = re.slice(0, nl.reStart)
+      const nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
+      let nlAfter = re.slice(nl.reEnd)
+      const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter
+
+      // Handle nested stuff like *(*.js|!(*.json)), where open parens
+      // mean that we should *not* include the ) in the bit that is considered
+      // "after" the negated section.
+      const closeParensBefore = nlBefore.split(')').length
+      const openParensBefore = nlBefore.split('(').length - closeParensBefore
+      let cleanAfter = nlAfter
+      for (let i = 0; i < openParensBefore; i++) {
+        cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
+      }
+      nlAfter = cleanAfter
+
+      const dollar = nlAfter === '' && isSub !== SUBPARSE ? '(?:$|\\/)' : ''
+
+      re = nlBefore + nlFirst + nlAfter + dollar + nlLast
+    }
+
+    // if the re is not "" at this point, then we need to make sure
+    // it doesn't match against an empty path part.
+    // Otherwise a/* will match a/, which it should not.
+    if (re !== '' && hasMagic) {
+      re = '(?=.)' + re
+    }
+
+    if (addPatternStart) {
+      re = patternStart() + re
+    }
+
+    // parsing just a piece of a larger pattern.
+    if (isSub === SUBPARSE) {
+      return [re, hasMagic]
+    }
+
+    // if it's nocase, and the lcase/uppercase don't match, it's magic
+    if (options.nocase && !hasMagic) {
+      hasMagic = pattern.toUpperCase() !== pattern.toLowerCase()
+    }
+
+    // skip the regexp for non-magical patterns
+    // unescape anything in it, though, so that it'll be
+    // an exact match against a file etc.
+    if (!hasMagic) {
+      return globUnescape(pattern)
+    }
+
+    const flags = options.nocase ? 'i' : ''
+    try {
+      return Object.assign(new RegExp('^' + re + '$', flags), {
+        _glob: pattern,
+        _src: re,
+      })
+    } catch (er) /* istanbul ignore next - should be impossible */ {
+      // If it was an invalid regular expression, then it can't match
+      // anything.  This trick looks for a character after the end of
+      // the string, which is of course impossible, except in multi-line
+      // mode, but it's not a /m regex.
+      return new RegExp('$.')
+    }
+  }
+
+  makeRe () {
+    if (this.regexp || this.regexp === false) return this.regexp
+
+    // at this point, this.set is a 2d array of partial
+    // pattern strings, or "**".
+    //
+    // It's better to use .match().  This function shouldn't
+    // be used, really, but it's pretty convenient sometimes,
+    // when you just want to work with a regex.
+    const set = this.set
+
+    if (!set.length) {
+      this.regexp = false
+      return this.regexp
+    }
+    const options = this.options
+
+    const twoStar = options.noglobstar ? star
+      : options.dot ? twoStarDot
+      : twoStarNoDot
+    const flags = options.nocase ? 'i' : ''
+
+    // coalesce globstars and regexpify non-globstar patterns
+    // if it's the only item, then we just do one twoStar
+    // if it's the first, and there are more, prepend (\/|twoStar\/)? to next
+    // if it's the last, append (\/twoStar|) to previous
+    // if it's in the middle, append (\/|\/twoStar\/) to previous
+    // then filter out GLOBSTAR symbols
+    let re = set.map(pattern => {
+      pattern = pattern.map(p =>
+        typeof p === 'string' ? regExpEscape(p)
+        : p === GLOBSTAR ? GLOBSTAR
+        : p._src
+      ).reduce((set, p) => {
+        if (!(set[set.length - 1] === GLOBSTAR && p === GLOBSTAR)) {
+          set.push(p)
+        }
+        return set
+      }, [])
+      pattern.forEach((p, i) => {
+        if (p !== GLOBSTAR || pattern[i-1] === GLOBSTAR) {
+          return
+        }
+        if (i === 0) {
+          if (pattern.length > 1) {
+            pattern[i+1] = '(?:\\\/|' + twoStar + '\\\/)?' + pattern[i+1]
+          } else {
+            pattern[i] = twoStar
+          }
+        } else if (i === pattern.length - 1) {
+          pattern[i-1] += '(?:\\\/|' + twoStar + ')?'
+        } else {
+          pattern[i-1] += '(?:\\\/|\\\/' + twoStar + '\\\/)' + pattern[i+1]
+          pattern[i+1] = GLOBSTAR
+        }
+      })
+      return pattern.filter(p => p !== GLOBSTAR).join('/')
+    }).join('|')
+
+    // must match entire pattern
+    // ending in a * or ** will make it less strict.
+    re = '^(?:' + re + ')$'
+
+    // can match anything, as long as it's not this.
+    if (this.negate) re = '^(?!' + re + ').*$'
+
+    try {
+      this.regexp = new RegExp(re, flags)
+    } catch (ex) /* istanbul ignore next - should be impossible */ {
+      this.regexp = false
+    }
+    return this.regexp
+  }
+
+  match (f, partial = this.partial) {
+    this.debug('match', f, this.pattern)
+    // short-circuit in the case of busted things.
+    // comments, etc.
+    if (this.comment) return false
+    if (this.empty) return f === ''
+
+    if (f === '/' && partial) return true
+
+    const options = this.options
+
+    // windows: need to use /, not \
+    if (path.sep !== '/') {
+      f = f.split(path.sep).join('/')
+    }
+
+    // treat the test path as a set of pathparts.
+    f = f.split(slashSplit)
+    this.debug(this.pattern, 'split', f)
+
+    // just ONE of the pattern sets in this.set needs to match
+    // in order for it to be valid.  If negating, then just one
+    // match means that we have failed.
+    // Either way, return on the first hit.
+
+    const set = this.set
+    this.debug(this.pattern, 'set', set)
+
+    // Find the basename of the path by looking for the last non-empty segment
+    let filename
+    for (let i = f.length - 1; i >= 0; i--) {
+      filename = f[i]
+      if (filename) break
+    }
+
+    for (let i = 0; i < set.length; i++) {
+      const pattern = set[i]
+      let file = f
+      if (options.matchBase && pattern.length === 1) {
+        file = [filename]
+      }
+      const hit = this.matchOne(file, pattern, partial)
+      if (hit) {
+        if (options.flipNegate) return true
+        return !this.negate
+      }
+    }
+
+    // didn't get any hits.  this is success if it's a negative
+    // pattern, failure otherwise.
+    if (options.flipNegate) return false
+    return this.negate
+  }
+
+  static defaults (def) {
+    return minimatch.defaults(def).Minimatch
+  }
+}
+
+minimatch.Minimatch = Minimatch
diff --git a/node_modules/filelist/node_modules/minimatch/package.json b/node_modules/filelist/node_modules/minimatch/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..c8809dbb3119d9d3a3348242ae4b9ff393c3c57a
--- /dev/null
+++ b/node_modules/filelist/node_modules/minimatch/package.json
@@ -0,0 +1,35 @@
+{
+  "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
+  "name": "minimatch",
+  "description": "a glob matcher in javascript",
+  "publishConfig": {
+    "tag": "legacy-v5"
+  },
+  "version": "5.1.6",
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/isaacs/minimatch.git"
+  },
+  "main": "minimatch.js",
+  "scripts": {
+    "test": "tap",
+    "snap": "tap",
+    "preversion": "npm test",
+    "postversion": "npm publish",
+    "prepublishOnly": "git push origin --follow-tags"
+  },
+  "engines": {
+    "node": ">=10"
+  },
+  "dependencies": {
+    "brace-expansion": "^2.0.1"
+  },
+  "devDependencies": {
+    "tap": "^16.3.2"
+  },
+  "license": "ISC",
+  "files": [
+    "minimatch.js",
+    "lib"
+  ]
+}
diff --git a/node_modules/filelist/package.json b/node_modules/filelist/package.json
index 99210369ae23e2e1b8c632dcdf5a502d8c356101..8a90586aa017af0f88c8c796ecb0176989a363af 100644
--- a/node_modules/filelist/package.json
+++ b/node_modules/filelist/package.json
@@ -1,6 +1,6 @@
 {
   "name": "filelist",
-  "version": "1.0.2",
+  "version": "1.0.4",
   "description": "Lazy-evaluating list of files, based on globs or regex patterns",
   "main": "index.js",
   "types": "index.d.ts",
@@ -23,6 +23,6 @@
   },
   "homepage": "https://github.com/mde/filelist",
   "dependencies": {
-    "minimatch": "^3.0.4"
+    "minimatch": "^5.0.1"
   }
 }
diff --git a/node_modules/has-flag/index.d.ts b/node_modules/has-flag/index.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a0a48c89112785902cb109a27475840fd0952de8
--- /dev/null
+++ b/node_modules/has-flag/index.d.ts
@@ -0,0 +1,39 @@
+/**
+Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag.
+
+@param flag - CLI flag to look for. The `--` prefix is optional.
+@param argv - CLI arguments. Default: `process.argv`.
+@returns Whether the flag exists.
+
+@example
+```
+// $ ts-node foo.ts -f --unicorn --foo=bar -- --rainbow
+
+// foo.ts
+import hasFlag = require('has-flag');
+
+hasFlag('unicorn');
+//=> true
+
+hasFlag('--unicorn');
+//=> true
+
+hasFlag('f');
+//=> true
+
+hasFlag('-f');
+//=> true
+
+hasFlag('foo=bar');
+//=> true
+
+hasFlag('foo');
+//=> false
+
+hasFlag('rainbow');
+//=> false
+```
+*/
+declare function hasFlag(flag: string, argv?: string[]): boolean;
+
+export = hasFlag;
diff --git a/node_modules/has-flag/index.js b/node_modules/has-flag/index.js
index 5139728fba6a264353ecb5abd00135dabf8a922d..b6f80b1f8ffd7658a11af977a9df3c296008d4cd 100644
--- a/node_modules/has-flag/index.js
+++ b/node_modules/has-flag/index.js
@@ -1,8 +1,8 @@
 'use strict';
-module.exports = (flag, argv) => {
-	argv = argv || process.argv;
+
+module.exports = (flag, argv = process.argv) => {
 	const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
-	const pos = argv.indexOf(prefix + flag);
-	const terminatorPos = argv.indexOf('--');
-	return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
+	const position = argv.indexOf(prefix + flag);
+	const terminatorPosition = argv.indexOf('--');
+	return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
 };
diff --git a/node_modules/has-flag/package.json b/node_modules/has-flag/package.json
index e1eb17a15ed8808af7bd7085dc398108d9920ba2..a9cba4b856d046212a2a2f13fb911ae1deb4c3b5 100644
--- a/node_modules/has-flag/package.json
+++ b/node_modules/has-flag/package.json
@@ -1,44 +1,46 @@
 {
-  "name": "has-flag",
-  "version": "3.0.0",
-  "description": "Check if argv has a specific flag",
-  "license": "MIT",
-  "repository": "sindresorhus/has-flag",
-  "author": {
-    "name": "Sindre Sorhus",
-    "email": "sindresorhus@gmail.com",
-    "url": "sindresorhus.com"
-  },
-  "engines": {
-    "node": ">=4"
-  },
-  "scripts": {
-    "test": "xo && ava"
-  },
-  "files": [
-    "index.js"
-  ],
-  "keywords": [
-    "has",
-    "check",
-    "detect",
-    "contains",
-    "find",
-    "flag",
-    "cli",
-    "command-line",
-    "argv",
-    "process",
-    "arg",
-    "args",
-    "argument",
-    "arguments",
-    "getopt",
-    "minimist",
-    "optimist"
-  ],
-  "devDependencies": {
-    "ava": "*",
-    "xo": "*"
-  }
+	"name": "has-flag",
+	"version": "4.0.0",
+	"description": "Check if argv has a specific flag",
+	"license": "MIT",
+	"repository": "sindresorhus/has-flag",
+	"author": {
+		"name": "Sindre Sorhus",
+		"email": "sindresorhus@gmail.com",
+		"url": "sindresorhus.com"
+	},
+	"engines": {
+		"node": ">=8"
+	},
+	"scripts": {
+		"test": "xo && ava && tsd"
+	},
+	"files": [
+		"index.js",
+		"index.d.ts"
+	],
+	"keywords": [
+		"has",
+		"check",
+		"detect",
+		"contains",
+		"find",
+		"flag",
+		"cli",
+		"command-line",
+		"argv",
+		"process",
+		"arg",
+		"args",
+		"argument",
+		"arguments",
+		"getopt",
+		"minimist",
+		"optimist"
+	],
+	"devDependencies": {
+		"ava": "^1.4.1",
+		"tsd": "^0.7.2",
+		"xo": "^0.24.0"
+	}
 }
diff --git a/node_modules/has-flag/readme.md b/node_modules/has-flag/readme.md
index 677893c278a2e31f9671e83dd66fed51886cd258..3f72dff29a69612c14eaec559e2a11bcced48b5b 100644
--- a/node_modules/has-flag/readme.md
+++ b/node_modules/has-flag/readme.md
@@ -4,6 +4,20 @@
 
 Correctly stops looking after an `--` argument terminator.
 
+---
+
+<div align="center">
+	<b>
+		<a href="https://tidelift.com/subscription/pkg/npm-has-flag?utm_source=npm-has-flag&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
+	</b>
+	<br>
+	<sub>
+		Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
+	</sub>
+</div>
+
+---
+
 
 ## Install
 
@@ -65,6 +79,11 @@ Default: `process.argv`
 CLI arguments.
 
 
+## Security
+
+To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
+
+
 ## License
 
 MIT © [Sindre Sorhus](https://sindresorhus.com)
diff --git a/node_modules/jake/jakefile.js b/node_modules/jake/jakefile.js
index b0ae79bb888908c5b9ef0795e2d3ad84019910a5..8bcd75c0a927f002161ae7b4ba13327fc52727fa 100644
--- a/node_modules/jake/jakefile.js
+++ b/node_modules/jake/jakefile.js
@@ -49,16 +49,7 @@ jake.Task['publish:package'].directory = PROJECT_DIR;
 
 namespace('test', function () {
 
-  let integrationTest = task('integration', ['publish:package'], async function () {
-    let pkg = JSON.parse(fs.readFileSync(`${PROJECT_DIR}/package.json`).toString());
-    let version = pkg.version;
-
-    proc.execSync('rm -rf ./node_modules');
-    // Install from the actual package, run tests from the packaged binary
-    proc.execSync(`mkdir -p node_modules/.bin && mv ${PROJECT_DIR}/pkg/jake-v` +
-        `${version} node_modules/jake && ln -s ${process.cwd()}` +
-      '/node_modules/jake/bin/cli.js ./node_modules/.bin/jake');
-
+  let integrationTest = task('integration', async function () {
     let testArgs = [];
     if (process.env.filter) {
       testArgs.push(process.env.filter);
@@ -71,20 +62,18 @@ namespace('test', function () {
     });
     return new Promise((resolve, reject) => {
       spawned.on('exit', () => {
-        if (!(process.env.noclobber || process.env.noClobber)) {
-          proc.execSync('rm -rf tmp_publish && rm -rf package.json' +
-              ' && rm -rf package-lock.json && rm -rf node_modules');
-          // Rather than invoking 'clobber' task
-          jake.rmRf(`${PROJECT_DIR}/pkg`);
-        }
         resolve();
       });
     });
 
   });
-
   integrationTest.directory = `${PROJECT_DIR}/test/integration`;
 
+  let integrationClobber = task('integrationClobber', function () {
+    proc.execSync('rm -rf package.json pkg tmp_publish');
+  });
+  integrationClobber.directory = `${PROJECT_DIR}/test/integration`;
+
   let unitTest = task('unit', async function () {
     let testArgs = [];
     if (process.env.filter) {
@@ -97,9 +86,9 @@ namespace('test', function () {
       stdio: 'inherit'
     });
   });
-
   unitTest.directory = `${PROJECT_DIR}/test/unit`;
+
 });
 
 desc('Runs all tests');
-task('test', ['test:unit', 'test:integration']);
+task('test', ['test:unit', 'test:integration', 'test:integrationClobber']);
diff --git a/node_modules/jake/lib/jake.js b/node_modules/jake/lib/jake.js
index a463163c12f710d26240733c20b4358160f5fe0b..0bd439a84e1a8c774f224f4d59de34c9edb8d8c4 100644
--- a/node_modules/jake/lib/jake.js
+++ b/node_modules/jake/lib/jake.js
@@ -102,7 +102,7 @@ if (!global.jake) {
     };
 
     /**
-     * Displays the list of descriptions avaliable for tasks defined in
+     * Displays the list of descriptions available for tasks defined in
      * a Jakefile
      */
     this.showAllTaskDescriptions = function (f) {
@@ -113,6 +113,8 @@ if (!global.jake) {
       let name;
       let descr;
       let filter = typeof f == 'string' ? f : null;
+      let taskParams;
+      let len;
 
       for (p in jake.Task) {
         if (!Object.prototype.hasOwnProperty.call(jake.Task, p)) {
@@ -122,13 +124,17 @@ if (!global.jake) {
           continue;
         }
         task = jake.Task[p];
+        taskParams = task.params;
+
         // Record the length of the longest task name -- used for
         // pretty alignment of the task descriptions
         if (task.description) {
-          maxTaskNameLength = p.length > maxTaskNameLength ?
-            p.length : maxTaskNameLength;
+          len = p.length + taskParams.length;
+          maxTaskNameLength = len > maxTaskNameLength ?
+            len : maxTaskNameLength;
         }
       }
+
       // Print out each entry with descriptions neatly aligned
       for (p in jake.Task) {
         if (!Object.prototype.hasOwnProperty.call(jake.Task, p)) {
@@ -139,6 +145,11 @@ if (!global.jake) {
         }
         task = jake.Task[p];
 
+        taskParams = "";
+        if (task.params != "") {
+          taskParams = "[" + task.params + "]";
+        }
+
         //name = '\033[32m' + p + '\033[39m ';
         name = chalk.green(p);
 
@@ -147,9 +158,9 @@ if (!global.jake) {
           descr = chalk.gray('# ' + descr);
 
           // Create padding-string with calculated length
-          padding = (new Array(maxTaskNameLength - p.length + 2)).join(' ');
+          padding = (new Array(maxTaskNameLength - p.length - taskParams.length + 4)).join(' ');
 
-          console.log('jake ' + name + padding + descr);
+          console.log('jake ' + name + taskParams + padding + descr);
         }
       }
     };
diff --git a/node_modules/jake/lib/loader.js b/node_modules/jake/lib/loader.js
index 02ad26282581faf6b2e7ff538cd39523f28094f3..a71b82c0284e44ae6b005a2b6cf4c2f3f66eab31 100644
--- a/node_modules/jake/lib/loader.js
+++ b/node_modules/jake/lib/loader.js
@@ -43,6 +43,14 @@ const SUPPORTED_EXTENSIONS = {
     catch (e) {
       throw new Error('You have a LiveScript Jakefile, but have not installed LiveScript');
     }
+  },
+  'ts': function () {
+    try {
+      require('ts-node/register/transpile-only');
+    }
+    catch (e) {
+      throw new Error('You have a TypeScript Jakefile, but have not installed TypeScript and ts-node');
+    }
   }
 };
 const IMPLICIT_JAKEFILE_NAMES = [
diff --git a/node_modules/jake/lib/publish_task.js b/node_modules/jake/lib/publish_task.js
index f0cacfda0f16cb0c9f524c57c3eab95d9b7384db..9aa8985ffab877dc827234f70aa2a8390846d4f0 100644
--- a/node_modules/jake/lib/publish_task.js
+++ b/node_modules/jake/lib/publish_task.js
@@ -196,11 +196,11 @@ PublishTask.prototype = new (function () {
         if (definePack.taskStatus == jake.Task.runStatuses.DONE) {
           definePack.reenable(true);
         }
-        definePack.invoke();
-        // Set manually, completion happens in next tick, creating deadlock
-        definePack.taskStatus = jake.Task.runStatuses.DONE;
-        pack.invoke();
-        console.log('Created package for ' + self.name + ' v' + version);
+        definePack.execute();
+        definePack.on('complete', function () {
+          pack.invoke();
+          console.log('Created package for ' + self.name + ' v' + version);
+        });
       });
 
       task('publish', function () {
diff --git a/node_modules/jake/lib/task/task.js b/node_modules/jake/lib/task/task.js
index 9e8886fa04ff987a555aed874ec64b8c26afa976..c433982e484f464f1013437d29fd9c22a33fb68e 100644
--- a/node_modules/jake/lib/task/task.js
+++ b/node_modules/jake/lib/task/task.js
@@ -93,6 +93,10 @@ class Task extends EventEmitter {
     return this._getFullName();
   }
 
+  get params() {
+    return this._getParams();
+  }
+
   _initInvocationChain() {
     // Legacy global invocation chain
     jake._invocationChain.push(this);
@@ -414,6 +418,12 @@ class Task extends EventEmitter {
     return path.join(':');
   }
 
+  _getParams() {
+    if (!this.action) return "";
+    let params = new RegExp('(?:'+this.action.name+'\\s*|^)\\s*\\((.*?)\\)').exec(this.action.toString().replace(/\n/g, ''))[1].replace(/\/\*.*?\*\//g, '').replace(/ /g, '');
+    return params;
+  }
+
   static getBaseNamespacePath(fullName) {
     return fullName.split(':').slice(0, -1).join(':');
   }
diff --git a/node_modules/jake/package.json b/node_modules/jake/package.json
index 8c4a961a24228cd226bace60d0bec7963b98f02e..dce34ef3047efc98f596a723f4726e612fef6777 100644
--- a/node_modules/jake/package.json
+++ b/node_modules/jake/package.json
@@ -7,7 +7,7 @@
     "make",
     "rake"
   ],
-  "version": "10.8.2",
+  "version": "10.8.5",
   "author": "Matthew Eernisse <mde@fleegix.org> (http://fleegix.org)",
   "license": "Apache-2.0",
   "bin": {
@@ -26,10 +26,10 @@
   },
   "preferGlobal": true,
   "dependencies": {
+    "async": "^3.2.3",
+    "chalk": "^4.0.2",
     "filelist": "^1.0.1",
-    "minimatch": "^3.0.4",
-    "chalk": "^2.4.2",
-    "async": "0.9.x"
+    "minimatch": "^3.0.4"
   },
   "devDependencies": {
     "eslint": "^6.8.0",
@@ -37,6 +37,6 @@
     "q": "^1.5.1"
   },
   "engines": {
-    "node": "*"
+    "node": ">=10"
   }
 }
diff --git a/node_modules/jake/test/integration/concurrent.js b/node_modules/jake/test/integration/concurrent.js
index 4ae41e81085f8e6610b2197bd501440f615a3aed..8c63133698dd05e04dce27d2084fb6d3e8d57ab7 100644
--- a/node_modules/jake/test/integration/concurrent.js
+++ b/node_modules/jake/test/integration/concurrent.js
@@ -1,38 +1,41 @@
 let assert = require('assert');
 let exec = require('child_process').execSync;
 
+const PROJECT_DIR = process.env.PROJECT_DIR;
+const JAKE_CMD = `${PROJECT_DIR}/bin/cli.js`;
+
 suite('concurrent', function () {
 
   this.timeout(7000);
 
   test(' simple concurrent prerequisites 1', function () {
-    let out = exec('./node_modules/.bin/jake -q concurrent:simple1').toString().trim()
+    let out = exec(`${JAKE_CMD} -q concurrent:simple1`).toString().trim()
     assert.equal('Started A\nStarted B\nFinished B\nFinished A', out);
   });
 
   test(' simple concurrent prerequisites 2', function () {
-    let out = exec('./node_modules/.bin/jake -q concurrent:simple2').toString().trim()
+    let out = exec(`${JAKE_CMD} -q concurrent:simple2`).toString().trim()
     assert.equal('Started C\nStarted D\nFinished C\nFinished D', out);
   });
 
   test(' sequential concurrent prerequisites', function () {
-    let out = exec('./node_modules/.bin/jake -q concurrent:seqconcurrent').toString().trim()
+    let out = exec(`${JAKE_CMD} -q concurrent:seqconcurrent`).toString().trim()
     assert.equal('Started A\nStarted B\nFinished B\nFinished A\nStarted C\nStarted D\nFinished C\nFinished D', out);
   });
 
   test(' concurrent concurrent prerequisites', function () {
-    let out = exec('./node_modules/.bin/jake -q concurrent:concurrentconcurrent').toString().trim()
+    let out = exec(`${JAKE_CMD} -q concurrent:concurrentconcurrent`).toString().trim()
     assert.equal('Started A\nStarted B\nStarted C\nStarted D\nFinished B\nFinished C\nFinished A\nFinished D', out);
   });
 
   test(' concurrent prerequisites with subdependency', function () {
-    let out = exec('./node_modules/.bin/jake -q concurrent:subdep').toString().trim()
+    let out = exec(`${JAKE_CMD} -q concurrent:subdep`).toString().trim()
     assert.equal('Started A\nFinished A\nStarted Ba\nFinished Ba', out);
   });
 
   test(' failing in concurrent prerequisites', function () {
     try {
-      exec('./node_modules/.bin/jake -q concurrent:Cfail');
+      exec(`${JAKE_CMD} -q concurrent:Cfail`);
     }
     catch(err) {
       assert(err.message.indexOf('Command failed') > -1);
diff --git a/node_modules/jake/test/integration/file_task.js b/node_modules/jake/test/integration/file_task.js
index b48f07e7ad8426485d2d8d4f7d650fccde8fe4e7..a320ea2b3c6e6c593cd117fc36653d8ed4d07f66 100644
--- a/node_modules/jake/test/integration/file_task.js
+++ b/node_modules/jake/test/integration/file_task.js
@@ -17,6 +17,7 @@
 */
 
 const PROJECT_DIR = process.env.PROJECT_DIR;
+const JAKE_CMD = `${PROJECT_DIR}/bin/cli.js`;
 
 let assert = require('assert');
 let fs = require('fs');
@@ -39,10 +40,10 @@ suite('fileTask', function () {
 
   test('where a file-task prereq does not change with --always-make', function () {
     let out;
-    out = exec('./node_modules/.bin/jake -q fileTest:foo/from-src1.txt').toString().trim();
+    out = exec(`${JAKE_CMD} -q fileTest:foo/from-src1.txt`).toString().trim();
     assert.equal('fileTest:foo/src1.txt task\nfileTest:foo/from-src1.txt task',
       out);
-    out = exec('./node_modules/.bin/jake -q -B fileTest:foo/from-src1.txt').toString().trim();
+    out = exec(`${JAKE_CMD} -q -B fileTest:foo/from-src1.txt`).toString().trim();
     assert.equal('fileTest:foo/src1.txt task\nfileTest:foo/from-src1.txt task',
       out);
     cleanUpAndNext();
@@ -50,7 +51,7 @@ suite('fileTask', function () {
 
   test('concating two files', function () {
     let out;
-    out = exec('./node_modules/.bin/jake -q fileTest:foo/concat.txt').toString().trim();
+    out = exec(`${JAKE_CMD} -q fileTest:foo/concat.txt`).toString().trim();
     assert.equal('fileTest:foo/src1.txt task\ndefault task\nfileTest:foo/src2.txt task\n' +
           'fileTest:foo/concat.txt task', out);
     // Check to see the two files got concat'd
@@ -61,9 +62,9 @@ suite('fileTask', function () {
 
   test('where a file-task prereq does not change', function () {
     let out;
-    out = exec('./node_modules/.bin/jake -q fileTest:foo/from-src1.txt').toString().trim();
+    out = exec(`${JAKE_CMD} -q fileTest:foo/from-src1.txt`).toString().trim();
     assert.equal('fileTest:foo/src1.txt task\nfileTest:foo/from-src1.txt task', out);
-    out = exec('./node_modules/.bin/jake -q fileTest:foo/from-src1.txt').toString().trim();
+    out = exec(`${JAKE_CMD} -q fileTest:foo/from-src1.txt`).toString().trim();
     // Second time should be a no-op
     assert.equal('', out);
     cleanUpAndNext();
@@ -76,10 +77,10 @@ suite('fileTask', function () {
       fs.writeFileSync('./foo/src1.txt', '-SRC');
       // Task should run the first time
       let out;
-      out = exec('./node_modules/.bin/jake -q fileTest:foo/from-src1.txt').toString().trim();
+      out = exec(`${JAKE_CMD} -q fileTest:foo/from-src1.txt`).toString().trim();
       assert.equal('fileTest:foo/from-src1.txt task', out);
       // Task should not run on subsequent invocation
-      out = exec('./node_modules/.bin/jake -q fileTest:foo/from-src1.txt').toString().trim();
+      out = exec(`${JAKE_CMD} -q fileTest:foo/from-src1.txt`).toString().trim();
       assert.equal('', out);
       cleanUpAndNext(next);
     }, 1000);
@@ -90,11 +91,11 @@ suite('fileTask', function () {
     exec('mkdir -p ./foo');
     fs.writeFileSync('foo/prereq.txt', prereqData);
     let out;
-    out = exec('./node_modules/.bin/jake -q fileTest:foo/from-prereq.txt').toString().trim();
+    out = exec(`${JAKE_CMD} -q fileTest:foo/from-prereq.txt`).toString().trim();
     assert.equal('fileTest:foo/from-prereq.txt task', out);
     let data = fs.readFileSync(process.cwd() + '/foo/from-prereq.txt');
     assert.equal(prereqData, data.toString());
-    out = exec('./node_modules/.bin/jake -q fileTest:foo/from-prereq.txt').toString().trim();
+    out = exec(`${JAKE_CMD} -q fileTest:foo/from-prereq.txt`).toString().trim();
     // Second time should be a no-op
     assert.equal('', out);
     cleanUpAndNext();
@@ -105,17 +106,17 @@ suite('fileTask', function () {
     exec('mkdir -p ./foo');
     fs.writeFileSync('foo/prereq.txt', prereqData);
     let out;
-    out = exec('./node_modules/.bin/jake -q fileTest:foo/from-prereq.txt').toString().trim();
+    out = exec(`${JAKE_CMD} -q fileTest:foo/from-prereq.txt`).toString().trim();
     assert.equal('fileTest:foo/from-prereq.txt task', out);
     let data = fs.readFileSync(process.cwd() + '/foo/from-prereq.txt');
     assert.equal(prereqData, data.toString());
-    out = exec('./node_modules/.bin/jake -q -B fileTest:foo/from-prereq.txt').toString().trim();
+    out = exec(`${JAKE_CMD} -q -B fileTest:foo/from-prereq.txt`).toString().trim();
     assert.equal('fileTest:foo/from-prereq.txt task', out);
     cleanUpAndNext();
   });
 
   test('nested directory-task', function () {
-    exec('./node_modules/.bin/jake -q fileTest:foo/bar/baz/bamf.txt');
+    exec(`${JAKE_CMD} -q fileTest:foo/bar/baz/bamf.txt`);
     let data = fs.readFileSync(process.cwd() + '/foo/bar/baz/bamf.txt');
     assert.equal('w00t', data);
     cleanUpAndNext();
diff --git a/node_modules/jake/test/integration/jakelib/required_module.jake.js b/node_modules/jake/test/integration/jakelib/required_module.jake.js
index c63751d72c0532d678a22fb91a71e01a3c23581c..eae666ba248d2001dedcce2fd3080e06e850d94c 100644
--- a/node_modules/jake/test/integration/jakelib/required_module.jake.js
+++ b/node_modules/jake/test/integration/jakelib/required_module.jake.js
@@ -1,4 +1,4 @@
-let { task, namespace } = require("jake");
+let { task, namespace } = require(`${process.env.PROJECT_DIR}/lib/jake`);
 
 namespace('usingRequire', function () {
   task('test', () => {
diff --git a/node_modules/jake/test/integration/publish_task.js b/node_modules/jake/test/integration/publish_task.js
index 034fd94aa83d0dfb3b98626cea5ff039588eb37d..a941b30c57a4f1b7a94bfbf8359f49131da38d95 100644
--- a/node_modules/jake/test/integration/publish_task.js
+++ b/node_modules/jake/test/integration/publish_task.js
@@ -1,12 +1,15 @@
 let assert = require('assert');
 let exec = require('child_process').execSync;
 
+const PROJECT_DIR = process.env.PROJECT_DIR;
+const JAKE_CMD = `${PROJECT_DIR}/bin/cli.js`;
+
 suite('publishTask', function () {
 
   this.timeout(7000);
 
   test('default task', function () {
-    let out = exec('./node_modules/.bin/jake  -q publish').toString().trim();
+    let out = exec(`${JAKE_CMD} -q publish`).toString().trim();
     let expected = [
       'Fetched remote tags.'
       , 'On branch v0.0'
diff --git a/node_modules/jake/test/integration/rule.js b/node_modules/jake/test/integration/rule.js
index b837b1dd37cb1bd9bdded7f1057cc8c2150a0978..468db01344f25db3b2f8f8bcb38f56f02624adc3 100644
--- a/node_modules/jake/test/integration/rule.js
+++ b/node_modules/jake/test/integration/rule.js
@@ -17,6 +17,7 @@
 */
 
 const PROJECT_DIR = process.env.PROJECT_DIR;
+const JAKE_CMD = `${PROJECT_DIR}/bin/cli.js`;
 
 let assert = require('assert');
 let exec = require('child_process').execSync;
@@ -74,7 +75,7 @@ suite('rule', function () {
   });
 
   test('rule w/o pattern', function () {
-    let out = exec( './node_modules/.bin/jake -q  tmp').toString().trim();
+    let out = exec( `${JAKE_CMD} -q  tmp`).toString().trim();
     let output = [
       "tmp_dep2.c task"
       , "tmp_dep1.c task"
@@ -88,7 +89,7 @@ suite('rule', function () {
   });
 
   test('rule w pattern w/o folder w/o namespace', function () {
-    let out = exec( './node_modules/.bin/jake  -q  tmp_p').toString().trim();
+    let out = exec( `${JAKE_CMD}  -q  tmp_p`).toString().trim();
     let output = [
       "tmp_dep2.c task"
       , "tmp_dep1.c task"
@@ -103,7 +104,7 @@ suite('rule', function () {
   });
 
   test('rule w pattern w folder w/o namespace', function () {
-    let out = exec( './node_modules/.bin/jake  -q  tmp_pf').toString().trim();
+    let out = exec( `${JAKE_CMD}  -q  tmp_pf`).toString().trim();
     let output = [
       "tmpsrc/tmp_dep1.c task"
       , "cp tmpsrc/tmp_dep1.c tmpbin/tmp_dep1.oo task"
@@ -118,7 +119,7 @@ suite('rule', function () {
   });
 
   test.skip('rule w pattern w folder w namespace', function () {
-    let out = exec( './node_modules/.bin/jake -q   tmp_ns').toString().trim();
+    let out = exec( `${JAKE_CMD} -q   tmp_ns`).toString().trim();
     let output = [
       "tmpsrc/file2.c init task" // yes
       , "tmpsrc/tmp_dep2.c task" // no
@@ -135,7 +136,7 @@ suite('rule', function () {
   });
 
   test.skip('rule w chain w pattern w folder w namespace', function () {
-    let out = exec( './node_modules/.bin/jake -q tmp_cr').toString().trim();
+    let out = exec( `${JAKE_CMD} -q tmp_cr`).toString().trim();
     let output = [
       "chainrule init task"
       , "cp tmpsrc/file1.tex tmpbin/file1.dvi tex->dvi task"
@@ -159,7 +160,7 @@ suite('rule', function () {
       rmRf('foo.txt', {silent: true});
       rmRf('foo.html', {silent: true});
       try {
-        exec('./node_modules/.bin/jake  ' + key + ':test');
+        exec(`${JAKE_CMD}  ` + key + ':test');
       }
       catch(err) {
         // foo.txt prereq doesn't exist yet
@@ -170,7 +171,7 @@ suite('rule', function () {
 
     test('rule with source file now created (' + key  + ')', function () {
       fs.writeFileSync('foo.txt', '');
-      let out = exec('./node_modules/.bin/jake -q  ' + key + ':test').toString().trim();
+      let out = exec(`${JAKE_CMD} -q  ` + key + ':test').toString().trim();
       // Should run prereq and test task
       let output = [
         'created html'
@@ -182,7 +183,7 @@ suite('rule', function () {
     test('rule with source file modified (' + key  + ')', function (next) {
       setTimeout(function () {
         fs.writeFileSync('foo.txt', '');
-        let out = exec('./node_modules/.bin/jake -q  ' + key + ':test').toString().trim();
+        let out = exec(`${JAKE_CMD} -q  ` + key + ':test').toString().trim();
         // Should again run both prereq and test task
         let output = [
           'created html'
@@ -199,7 +200,7 @@ suite('rule', function () {
       // Remove just the source file
       fs.writeFileSync('foo.html', '');
       rmRf('foo.txt', {silent: true});
-      let out = exec('./node_modules/.bin/jake -q  ' + key + ':test').toString().trim();
+      let out = exec(`${JAKE_CMD} -q  ` + key + ':test').toString().trim();
       // Should treat existing objective file as plain file-task,
       // and just run test-task
       let output = [
diff --git a/node_modules/jake/test/integration/selfdep.js b/node_modules/jake/test/integration/selfdep.js
index 22d58d1259f33f5ada2a758aa4312ced4119632b..9ee7674ae6be3611b89c8f29df0587202850f3c1 100644
--- a/node_modules/jake/test/integration/selfdep.js
+++ b/node_modules/jake/test/integration/selfdep.js
@@ -1,6 +1,9 @@
 let assert = require('assert');
 let exec = require('child_process').execSync;
 
+const PROJECT_DIR = process.env.PROJECT_DIR;
+const JAKE_CMD = `${PROJECT_DIR}/bin/cli.js`;
+
 suite('selfDep', function () {
 
   this.timeout(7000);
@@ -18,7 +21,7 @@ suite('selfDep', function () {
 
   test('self dep const', function () {
     try {
-      exec('./node_modules/.bin/jake selfdepconst');
+      exec(`${JAKE_CMD} selfdepconst`);
     }
     catch(e) {
       assert(e.message.indexOf('dependency of itself') > -1)
@@ -27,7 +30,7 @@ suite('selfDep', function () {
 
   test('self dep dyn', function () {
     try {
-      exec('./node_modules/.bin/jake selfdepdyn');
+      exec(`${JAKE_CMD} selfdepdyn`);
     }
     catch(e) {
       assert(e.message.indexOf('dependency of itself') > -1)
diff --git a/node_modules/jake/test/integration/task_base.js b/node_modules/jake/test/integration/task_base.js
index 36e20e8838a3c0535cfb8a9fbbd0b0c9d661dcab..9aa501d7d5519bab5f1a4cfb1f0795d16685384c 100644
--- a/node_modules/jake/test/integration/task_base.js
+++ b/node_modules/jake/test/integration/task_base.js
@@ -2,36 +2,39 @@ let assert = require('assert');
 let h = require('./helpers');
 let exec = require('child_process').execSync;
 
+const PROJECT_DIR = process.env.PROJECT_DIR;
+const JAKE_CMD = `${PROJECT_DIR}/bin/cli.js`;
+
 suite('taskBase', function () {
 
   this.timeout(7000);
 
   test('default task', function () {
     let out;
-    out = exec('./node_modules/.bin/jake -q').toString().trim();
+    out = exec(`${JAKE_CMD} -q`).toString().trim();
     assert.equal(out, 'default task');
-    out = exec('./node_modules/.bin/jake -q default').toString().trim();
+    out = exec(`${JAKE_CMD} -q default`).toString().trim();
     assert.equal(out, 'default task');
   });
 
   test('task with no action', function () {
-    let out = exec('./node_modules/.bin/jake -q noAction').toString().trim();
+    let out = exec(`${JAKE_CMD} -q noAction`).toString().trim();
     assert.equal(out, 'default task');
   });
 
   test('a task with no action and no prereqs', function () {
-    exec('./node_modules/.bin/jake noActionNoPrereqs');
+    exec(`${JAKE_CMD} noActionNoPrereqs`);
   });
 
   test('a task that exists at the top-level, and not in the specified namespace, should error', function () {
-    let res = require('child_process').spawnSync('./node_modules/.bin/jake',
-    ['asdfasdfasdf:zerbofrangazoomy']);
+    let res = require('child_process').spawnSync(`${JAKE_CMD}`,
+      ['asdfasdfasdf:zerbofrangazoomy']);
     let err = res.stderr.toString();
     assert.ok(err.indexOf('Unknown task' > -1));
   });
 
   test('passing args to a task', function () {
-    let out = exec('./node_modules/.bin/jake -q argsEnvVars[foo,bar]').toString().trim();
+    let out = exec(`${JAKE_CMD} -q argsEnvVars[foo,bar]`).toString().trim();
     let parsed = h.parse(out);
     let args = parsed.args;
     assert.equal(args[0], 'foo');
@@ -39,7 +42,7 @@ suite('taskBase', function () {
   });
 
   test('a task with environment vars', function () {
-    let out = exec('./node_modules/.bin/jake -q argsEnvVars foo=bar baz=qux').toString().trim();
+    let out = exec(`${JAKE_CMD} -q argsEnvVars foo=bar baz=qux`).toString().trim();
     let parsed = h.parse(out);
     let env = parsed.env;
     assert.equal(env.foo, 'bar');
@@ -47,7 +50,7 @@ suite('taskBase', function () {
   });
 
   test('passing args and using environment vars', function () {
-    let out = exec('./node_modules/.bin/jake -q argsEnvVars[foo,bar] foo=bar baz=qux').toString().trim();
+    let out = exec(`${JAKE_CMD} -q argsEnvVars[foo,bar] foo=bar baz=qux`).toString().trim();
     let parsed = h.parse(out);
     let args = parsed.args;
     let env = parsed.env;
@@ -58,53 +61,53 @@ suite('taskBase', function () {
   });
 
   test('a simple prereq', function () {
-    let out = exec('./node_modules/.bin/jake -q foo:baz').toString().trim();
+    let out = exec(`${JAKE_CMD} -q foo:baz`).toString().trim();
     assert.equal(out, 'foo:bar task\nfoo:baz task');
   });
 
   test('a duplicate prereq only runs once', function () {
-    let out = exec('./node_modules/.bin/jake -q foo:asdf').toString().trim();
+    let out = exec(`${JAKE_CMD} -q foo:asdf`).toString().trim();
     assert.equal(out, 'foo:bar task\nfoo:baz task\nfoo:asdf task');
   });
 
   test('a prereq with command-line args', function () {
-    let out = exec('./node_modules/.bin/jake -q foo:qux').toString().trim();
+    let out = exec(`${JAKE_CMD} -q foo:qux`).toString().trim();
     assert.equal(out, 'foo:bar[asdf,qwer] task\nfoo:qux task');
   });
 
   test('a prereq with args via invoke', function () {
-    let out = exec('./node_modules/.bin/jake -q foo:frang[zxcv,uiop]').toString().trim();
+    let out = exec(`${JAKE_CMD} -q foo:frang[zxcv,uiop]`).toString().trim();
     assert.equal(out, 'foo:bar[zxcv,uiop] task\nfoo:frang task');
   });
 
   test('a prereq with args via execute', function () {
-    let out = exec('./node_modules/.bin/jake -q foo:zerb[zxcv,uiop]').toString().trim();
+    let out = exec(`${JAKE_CMD} -q foo:zerb[zxcv,uiop]`).toString().trim();
     assert.equal(out, 'foo:bar[zxcv,uiop] task\nfoo:zerb task');
   });
 
   test('repeating the task via execute', function () {
-    let out = exec('./node_modules/.bin/jake -q foo:voom').toString().trim();
+    let out = exec(`${JAKE_CMD} -q foo:voom`).toString().trim();
     assert.equal(out, 'foo:bar task\nfoo:bar task\ncomplete\ncomplete');
   });
 
   test('prereq execution-order', function () {
-    let out = exec('./node_modules/.bin/jake -q hoge:fuga').toString().trim();
+    let out = exec(`${JAKE_CMD} -q hoge:fuga`).toString().trim();
     assert.equal(out, 'hoge:hoge task\nhoge:piyo task\nhoge:fuga task');
   });
 
   test('basic async task', function () {
-    let out = exec('./node_modules/.bin/jake -q bar:bar').toString().trim();
+    let out = exec(`${JAKE_CMD} -q bar:bar`).toString().trim();
     assert.equal(out, 'bar:foo task\nbar:bar task');
   });
 
   test('promise async task', function () {
-    let out = exec('./node_modules/.bin/jake -q bar:dependOnpromise').toString().trim();
+    let out = exec(`${JAKE_CMD} -q bar:dependOnpromise`).toString().trim();
     assert.equal(out, 'bar:promise task\nbar:dependOnpromise task saw value 123654');
   });
 
   test('failing promise async task', function () {
     try {
-      exec('./node_modules/.bin/jake -q bar:brokenPromise');
+      exec(`${JAKE_CMD} -q bar:brokenPromise`);
     }
     catch(e) {
       assert(e.message.indexOf('Command failed') > -1);
@@ -112,19 +115,19 @@ suite('taskBase', function () {
   });
 
   test('that current-prereq index gets reset', function () {
-    let out = exec('./node_modules/.bin/jake -q hoge:kira').toString().trim();
+    let out = exec(`${JAKE_CMD} -q hoge:kira`).toString().trim();
     assert.equal(out, 'hoge:hoge task\nhoge:piyo task\nhoge:fuga task\n' +
         'hoge:charan task\nhoge:gero task\nhoge:kira task');
   });
 
   test('modifying a task by adding prereq during execution', function () {
-    let out = exec('./node_modules/.bin/jake -q voom').toString().trim();
+    let out = exec(`${JAKE_CMD} -q voom`).toString().trim();
     assert.equal(out, 2);
   });
 
   test('listening for task error-event', function () {
     try {
-      exec('./node_modules/.bin/jake -q vronk:groo').toString().trim();
+      exec(`${JAKE_CMD} -q vronk:groo`).toString().trim();
     }
     catch(e) {
       assert(e.message.indexOf('OMFGZONG') > -1);
@@ -132,32 +135,32 @@ suite('taskBase', function () {
   });
 
   test('listening for jake error-event', function () {
-    let out = exec('./node_modules/.bin/jake -q throwy').toString().trim();
+    let out = exec(`${JAKE_CMD} -q throwy`).toString().trim();
     assert(out.indexOf('Emitted\nError: I am bad') > -1);
   });
 
   test('listening for jake unhandledRejection-event', function () {
-    let out = exec('./node_modules/.bin/jake -q promiseRejecter').toString().trim();
+    let out = exec(`${JAKE_CMD} -q promiseRejecter`).toString().trim();
     assert.equal(out, '<promise rejected on purpose>');
   });
 
   test('large number of same prereqs', function () {
-    let out = exec('./node_modules/.bin/jake -q large:same').toString().trim();
+    let out = exec(`${JAKE_CMD} -q large:same`).toString().trim();
     assert.equal(out, 'large:leaf\nlarge:same');
   });
 
   test('large number of different prereqs', function () {
-    let out = exec('./node_modules/.bin/jake -q large:different').toString().trim();
+    let out = exec(`${JAKE_CMD} -q large:different`).toString().trim();
     assert.equal(out, 'leaf-12\nleaf-123\nlarge:different');
   });
 
   test('large number of different prereqs', function () {
-    let out = exec('./node_modules/.bin/jake -q usingRequire:test').toString().trim();
+    let out = exec(`${JAKE_CMD} -q usingRequire:test`).toString().trim();
     assert.equal(out, 'howdy test');
   });
 
   test('modifying a namespace by adding a new task', function () {
-    let out = exec('./node_modules/.bin/jake -q one:two').toString().trim();
+    let out = exec(`${JAKE_CMD} -q one:two`).toString().trim();
     assert.equal('one:one\none:two', out);
   });
 
diff --git a/node_modules/jake/usage.txt b/node_modules/jake/usage.txt
index 392b6d8f847afa7ff498340d8d9b471c0ad11daa..ea5f255042adb3f41cc8bb2d055433f13e153877 100644
--- a/node_modules/jake/usage.txt
+++ b/node_modules/jake/usage.txt
@@ -8,9 +8,9 @@ If no flags are given, Jake looks for a Jakefile or Jakefile.js in the current d
   -f,     --jakefile FILE            Use FILE as the Jakefile.
   -C,     --directory DIRECTORY      Change to DIRECTORY before running tasks.
   -B,     --always-make              Unconditionally make all targets.
-  -T/ls,  --tasks                 Display the tasks (matching optional PATTERN) with descriptions, then exit.
+  -T/-ls,  --tasks                 Display the tasks (matching optional PATTERN) with descriptions, then exit.
   -J,     --jakelibdir JAKELIBDIR    Auto-import any .jake files in JAKELIBDIR. (default is \'jakelib\')
   -h,     --help                     Display this help message.
-  -V/v,   --version                  Display the Jake version.
+  -V/-v,   --version                  Display the Jake version.
   -ar,    --allow-rejection          Keep running even after unhandled promise rejection
 
diff --git a/node_modules/minimist/.eslintrc b/node_modules/minimist/.eslintrc
new file mode 100644
index 0000000000000000000000000000000000000000..bd1a5e046b4148dfc6bfd15c8aa69c81ae809a28
--- /dev/null
+++ b/node_modules/minimist/.eslintrc
@@ -0,0 +1,29 @@
+{
+	"root": true,
+
+	"extends": "@ljharb/eslint-config/node/0.4",
+
+	"rules": {
+		"array-element-newline": 0,
+		"complexity": 0,
+		"func-style": [2, "declaration"],
+		"max-lines-per-function": 0,
+		"max-nested-callbacks": 1,
+		"max-statements-per-line": 1,
+		"max-statements": 0,
+		"multiline-comment-style": 0,
+		"no-continue": 1,
+		"no-param-reassign": 1,
+		"no-restricted-syntax": 1,
+		"object-curly-newline": 0,
+	},
+
+	"overrides": [
+		{
+			"files": "test/**",
+			"rules": {
+				"camelcase": 0,
+			},
+		},
+	]
+}
diff --git a/node_modules/minimist/.github/FUNDING.yml b/node_modules/minimist/.github/FUNDING.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a9366222e92a9f9a7a2a4c4cf7cf0f011510924d
--- /dev/null
+++ b/node_modules/minimist/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: [ljharb]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: npm/minimist
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/node_modules/minimist/.nycrc b/node_modules/minimist/.nycrc
new file mode 100644
index 0000000000000000000000000000000000000000..55c3d29367a4216abea3dc5eaa48b59826da355b
--- /dev/null
+++ b/node_modules/minimist/.nycrc
@@ -0,0 +1,14 @@
+{
+	"all": true,
+	"check-coverage": false,
+	"reporter": ["text-summary", "text", "html", "json"],
+	"lines": 86,
+	"statements": 85.93,
+	"functions": 82.43,
+	"branches": 76.06,
+	"exclude": [
+		"coverage",
+		"example",
+		"test"
+	]
+}
diff --git a/node_modules/minimist/CHANGELOG.md b/node_modules/minimist/CHANGELOG.md
new file mode 100644
index 0000000000000000000000000000000000000000..c9a1e15e6c2fe73a0ebf35040fef031b46437ba6
--- /dev/null
+++ b/node_modules/minimist/CHANGELOG.md
@@ -0,0 +1,298 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [v1.2.8](https://github.com/minimistjs/minimist/compare/v1.2.7...v1.2.8) - 2023-02-09
+
+### Merged
+
+- [Fix] Fix long option followed by single dash [`#17`](https://github.com/minimistjs/minimist/pull/17)
+- [Tests] Remove duplicate test [`#12`](https://github.com/minimistjs/minimist/pull/12)
+- [Fix] opt.string works with multiple aliases [`#10`](https://github.com/minimistjs/minimist/pull/10)
+
+### Fixed
+
+- [Fix] Fix long option followed by single dash (#17) [`#15`](https://github.com/minimistjs/minimist/issues/15)
+- [Tests] Remove duplicate test (#12) [`#8`](https://github.com/minimistjs/minimist/issues/8)
+- [Fix] Fix long option followed by single dash [`#15`](https://github.com/minimistjs/minimist/issues/15)
+- [Fix] opt.string works with multiple aliases (#10) [`#9`](https://github.com/minimistjs/minimist/issues/9)
+- [Fix] Fix handling of short option with non-trivial equals [`#5`](https://github.com/minimistjs/minimist/issues/5)
+- [Tests] Remove duplicate test [`#8`](https://github.com/minimistjs/minimist/issues/8)
+- [Fix] opt.string works with multiple aliases [`#9`](https://github.com/minimistjs/minimist/issues/9)
+
+### Commits
+
+- Merge tag 'v0.2.3' [`a026794`](https://github.com/minimistjs/minimist/commit/a0267947c7870fc5847cf2d437fbe33f392767da)
+- [eslint] fix indentation and whitespace [`5368ca4`](https://github.com/minimistjs/minimist/commit/5368ca4147e974138a54cc0dc4cea8f756546b70)
+- [eslint] fix indentation and whitespace [`e5f5067`](https://github.com/minimistjs/minimist/commit/e5f5067259ceeaf0b098d14bec910f87e58708c7)
+- [eslint] more cleanup [`62fde7d`](https://github.com/minimistjs/minimist/commit/62fde7d935f83417fb046741531a9e2346a36976)
+- [eslint] more cleanup [`36ac5d0`](https://github.com/minimistjs/minimist/commit/36ac5d0d95e4947d074e5737d94814034ca335d1)
+- [meta] add `auto-changelog` [`73923d2`](https://github.com/minimistjs/minimist/commit/73923d223553fca08b1ba77e3fbc2a492862ae4c)
+- [actions] add reusable workflows [`d80727d`](https://github.com/minimistjs/minimist/commit/d80727df77bfa9e631044d7f16368d8f09242c91)
+- [eslint] add eslint; rules to enable later are warnings [`48bc06a`](https://github.com/minimistjs/minimist/commit/48bc06a1b41f00e9cdf183db34f7a51ba70e98d4)
+- [eslint] fix indentation [`34b0f1c`](https://github.com/minimistjs/minimist/commit/34b0f1ccaa45183c3c4f06a91f9b405180a6f982)
+- [readme] rename and add badges [`5df0fe4`](https://github.com/minimistjs/minimist/commit/5df0fe49211bd09a3636f8686a7cb3012c3e98f0)
+- [Dev Deps] switch from `covert` to `nyc` [`a48b128`](https://github.com/minimistjs/minimist/commit/a48b128fdb8d427dfb20a15273f83e38d97bef07)
+- [Dev Deps] update `covert`, `tape`; remove unnecessary `tap` [`f0fb958`](https://github.com/minimistjs/minimist/commit/f0fb958e9a1fe980cdffc436a211b0bda58f621b)
+- [meta] create FUNDING.yml; add `funding` in package.json [`3639e0c`](https://github.com/minimistjs/minimist/commit/3639e0c819359a366387e425ab6eabf4c78d3caa)
+- [meta] use `npmignore` to autogenerate an npmignore file [`be2e038`](https://github.com/minimistjs/minimist/commit/be2e038c342d8333b32f0fde67a0026b79c8150e)
+- Only apps should have lockfiles [`282b570`](https://github.com/minimistjs/minimist/commit/282b570e7489d01b03f2d6d3dabf79cd3e5f84cf)
+- isConstructorOrProto adapted from PR [`ef9153f`](https://github.com/minimistjs/minimist/commit/ef9153fc52b6cea0744b2239921c5dcae4697f11)
+- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`098873c`](https://github.com/minimistjs/minimist/commit/098873c213cdb7c92e55ae1ef5aa1af3a8192a79)
+- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`3124ed3`](https://github.com/minimistjs/minimist/commit/3124ed3e46306301ebb3c834874ce0241555c2c4)
+- [meta] add `safe-publish-latest` [`4b927de`](https://github.com/minimistjs/minimist/commit/4b927de696d561c636b4f43bf49d4597cb36d6d6)
+- [Tests] add `aud` in `posttest` [`b32d9bd`](https://github.com/minimistjs/minimist/commit/b32d9bd0ab340f4e9f8c3a97ff2a4424f25fab8c)
+- [meta] update repo URLs [`f9fdfc0`](https://github.com/minimistjs/minimist/commit/f9fdfc032c54884d9a9996a390c63cd0719bbe1a)
+- [actions] Avoid 0.6 tests due to build failures [`ba92fe6`](https://github.com/minimistjs/minimist/commit/ba92fe6ebbdc0431cca9a2ea8f27beb492f5e4ec)
+- [Dev Deps] update `tape` [`950eaa7`](https://github.com/minimistjs/minimist/commit/950eaa74f112e04d23e9c606c67472c46739b473)
+- [Dev Deps] add missing `npmignore` dev dep [`3226afa`](https://github.com/minimistjs/minimist/commit/3226afaf09e9d127ca369742437fe6e88f752d6b)
+- Merge tag 'v0.2.2' [`980d7ac`](https://github.com/minimistjs/minimist/commit/980d7ac61a0b4bd552711251ac107d506b23e41f)
+
+## [v1.2.7](https://github.com/minimistjs/minimist/compare/v1.2.6...v1.2.7) - 2022-10-10
+
+### Commits
+
+- [meta] add `auto-changelog` [`0ebf4eb`](https://github.com/minimistjs/minimist/commit/0ebf4ebcd5f7787a5524d31a849ef41316b83c3c)
+- [actions] add reusable workflows [`e115b63`](https://github.com/minimistjs/minimist/commit/e115b63fa9d3909f33b00a2db647ff79068388de)
+- [eslint] add eslint; rules to enable later are warnings [`f58745b`](https://github.com/minimistjs/minimist/commit/f58745b9bb84348e1be72af7dbba5840c7c13013)
+- [Dev Deps] switch from `covert` to `nyc` [`ab03356`](https://github.com/minimistjs/minimist/commit/ab033567b9c8b31117cb026dc7f1e592ce455c65)
+- [readme] rename and add badges [`236f4a0`](https://github.com/minimistjs/minimist/commit/236f4a07e4ebe5ee44f1496ec6974991ab293ffd)
+- [meta] create FUNDING.yml; add `funding` in package.json [`783a49b`](https://github.com/minimistjs/minimist/commit/783a49bfd47e8335d3098a8cac75662cf71eb32a)
+- [meta] use `npmignore` to autogenerate an npmignore file [`f81ece6`](https://github.com/minimistjs/minimist/commit/f81ece6aaec2fa14e69ff4f1e0407a8c4e2635a2)
+- Only apps should have lockfiles [`56cad44`](https://github.com/minimistjs/minimist/commit/56cad44c7f879b9bb5ec18fcc349308024a89bfc)
+- [Dev Deps] update `covert`, `tape`; remove unnecessary `tap` [`49c5f9f`](https://github.com/minimistjs/minimist/commit/49c5f9fb7e6a92db9eb340cc679de92fb3aacded)
+- [Tests] add `aud` in `posttest` [`228ae93`](https://github.com/minimistjs/minimist/commit/228ae938f3cd9db9dfd8bd7458b076a7b2aef280)
+- [meta] add `safe-publish-latest` [`01fc23f`](https://github.com/minimistjs/minimist/commit/01fc23f5104f85c75059972e01dd33796ab529ff)
+- [meta] update repo URLs [`6b164c7`](https://github.com/minimistjs/minimist/commit/6b164c7d68e0b6bf32f894699effdfb7c63041dd)
+
+## [v1.2.6](https://github.com/minimistjs/minimist/compare/v1.2.5...v1.2.6) - 2022-03-21
+
+### Commits
+
+- test from prototype pollution PR [`bc8ecee`](https://github.com/minimistjs/minimist/commit/bc8ecee43875261f4f17eb20b1243d3ed15e70eb)
+- isConstructorOrProto adapted from PR [`c2b9819`](https://github.com/minimistjs/minimist/commit/c2b981977fa834b223b408cfb860f933c9811e4d)
+- security notice for additional prototype pollution issue [`ef88b93`](https://github.com/minimistjs/minimist/commit/ef88b9325f77b5ee643ccfc97e2ebda577e4c4e2)
+
+## [v1.2.5](https://github.com/minimistjs/minimist/compare/v1.2.4...v1.2.5) - 2020-03-12
+
+## [v1.2.4](https://github.com/minimistjs/minimist/compare/v1.2.3...v1.2.4) - 2020-03-11
+
+### Commits
+
+- security notice [`4cf1354`](https://github.com/minimistjs/minimist/commit/4cf1354839cb972e38496d35e12f806eea92c11f)
+- additional test for constructor prototype pollution [`1043d21`](https://github.com/minimistjs/minimist/commit/1043d212c3caaf871966e710f52cfdf02f9eea4b)
+
+## [v1.2.3](https://github.com/minimistjs/minimist/compare/v1.2.2...v1.2.3) - 2020-03-10
+
+### Commits
+
+- more failing proto pollution tests [`13c01a5`](https://github.com/minimistjs/minimist/commit/13c01a5327736903704984b7f65616b8476850cc)
+- even more aggressive checks for protocol pollution [`38a4d1c`](https://github.com/minimistjs/minimist/commit/38a4d1caead72ef99e824bb420a2528eec03d9ab)
+
+## [v1.2.2](https://github.com/minimistjs/minimist/compare/v1.2.1...v1.2.2) - 2020-03-10
+
+### Commits
+
+- failing test for protocol pollution [`0efed03`](https://github.com/minimistjs/minimist/commit/0efed0340ec8433638758f7ca0c77cb20a0bfbab)
+- cleanup [`67d3722`](https://github.com/minimistjs/minimist/commit/67d3722413448d00a62963d2d30c34656a92d7e2)
+- console.dir -&gt; console.log [`47acf72`](https://github.com/minimistjs/minimist/commit/47acf72c715a630bf9ea013867f47f1dd69dfc54)
+- don't assign onto __proto__ [`63e7ed0`](https://github.com/minimistjs/minimist/commit/63e7ed05aa4b1889ec2f3b196426db4500cbda94)
+
+## [v1.2.1](https://github.com/minimistjs/minimist/compare/v1.2.0...v1.2.1) - 2020-03-10
+
+### Merged
+
+- move the `opts['--']` example back where it belongs [`#63`](https://github.com/minimistjs/minimist/pull/63)
+
+### Commits
+
+- add test [`6be5dae`](https://github.com/minimistjs/minimist/commit/6be5dae35a32a987bcf4137fcd6c19c5200ee909)
+- fix bad boolean regexp [`ac3fc79`](https://github.com/minimistjs/minimist/commit/ac3fc796e63b95128fdbdf67ea7fad71bd59aa76)
+
+## [v1.2.0](https://github.com/minimistjs/minimist/compare/v1.1.3...v1.2.0) - 2015-08-24
+
+### Commits
+
+- failing -k=v short test [`63416b8`](https://github.com/minimistjs/minimist/commit/63416b8cd1d0d70e4714564cce465a36e4dd26d7)
+- kv short fix [`6bbe145`](https://github.com/minimistjs/minimist/commit/6bbe14529166245e86424f220a2321442fe88dc3)
+- failing kv short test [`f72ab7f`](https://github.com/minimistjs/minimist/commit/f72ab7f4572adc52902c9b6873cc969192f01b10)
+- fixed kv test [`f5a48c3`](https://github.com/minimistjs/minimist/commit/f5a48c3e50e40ca54f00c8e84de4b4d6e9897fa8)
+- enforce space between arg key and value [`86b321a`](https://github.com/minimistjs/minimist/commit/86b321affe648a8e016c095a4f0efa9d9074f502)
+
+## [v1.1.3](https://github.com/minimistjs/minimist/compare/v1.1.2...v1.1.3) - 2015-08-06
+
+### Commits
+
+- add failing test - boolean alias array [`0fa3c5b`](https://github.com/minimistjs/minimist/commit/0fa3c5b3dd98551ddecf5392831b4c21211743fc)
+- fix boolean values with multiple aliases [`9c0a6e7`](https://github.com/minimistjs/minimist/commit/9c0a6e7de25a273b11bbf9a7464f0bd833779795)
+
+## [v1.1.2](https://github.com/minimistjs/minimist/compare/v1.1.1...v1.1.2) - 2015-07-22
+
+### Commits
+
+- Convert boolean arguments to boolean values [`8f3dc27`](https://github.com/minimistjs/minimist/commit/8f3dc27cf833f1d54671b6d0bcb55c2fe19672a9)
+- use non-ancient npm, node 0.12 and iojs [`61ed1d0`](https://github.com/minimistjs/minimist/commit/61ed1d034b9ec7282764ce76f3992b1a0b4906ae)
+- an older npm for 0.8 [`25cf778`](https://github.com/minimistjs/minimist/commit/25cf778b1220e7838a526832ad6972f75244054f)
+
+## [v1.1.1](https://github.com/minimistjs/minimist/compare/v1.1.0...v1.1.1) - 2015-03-10
+
+### Commits
+
+- check that they type of a value is a boolean, not just that it is currently set to a boolean [`6863198`](https://github.com/minimistjs/minimist/commit/6863198e36139830ff1f20ffdceaddd93f2c1db9)
+- upgrade tape, fix type issues from old tape version [`806712d`](https://github.com/minimistjs/minimist/commit/806712df91604ed02b8e39aa372b84aea659ee34)
+- test for setting a boolean to a null default [`8c444fe`](https://github.com/minimistjs/minimist/commit/8c444fe89384ded7d441c120915ea60620b01dd3)
+- if the previous value was a boolean, without an default (or with an alias) don't make an array either [`e5f419a`](https://github.com/minimistjs/minimist/commit/e5f419a3b5b3bc3f9e5ac71b7040621af70ed2dd)
+
+## [v1.1.0](https://github.com/minimistjs/minimist/compare/v1.0.0...v1.1.0) - 2014-08-10
+
+### Commits
+
+- add support for handling "unknown" options not registered with the parser. [`6f3cc5d`](https://github.com/minimistjs/minimist/commit/6f3cc5d4e84524932a6ef2ce3592acc67cdd4383)
+- reformat package.json [`02ed371`](https://github.com/minimistjs/minimist/commit/02ed37115194d3697ff358e8e25e5e66bab1d9f8)
+- coverage script [`e5531ba`](https://github.com/minimistjs/minimist/commit/e5531ba0479da3b8138d3d8cac545d84ccb1c8df)
+- extra fn to get 100% coverage again [`a6972da`](https://github.com/minimistjs/minimist/commit/a6972da89e56bf77642f8ec05a13b6558db93498)
+
+## [v1.0.0](https://github.com/minimistjs/minimist/compare/v0.2.3...v1.0.0) - 2014-08-10
+
+### Commits
+
+- added stopEarly option [`471c7e4`](https://github.com/minimistjs/minimist/commit/471c7e4a7e910fc7ad8f9df850a186daf32c64e9)
+- fix list [`fef6ae7`](https://github.com/minimistjs/minimist/commit/fef6ae79c38b9dc1c49569abb7cd04eb965eac5e)
+
+## [v0.2.3](https://github.com/minimistjs/minimist/compare/v0.2.2...v0.2.3) - 2023-02-09
+
+### Merged
+
+- [Fix] Fix long option followed by single dash [`#17`](https://github.com/minimistjs/minimist/pull/17)
+- [Tests] Remove duplicate test [`#12`](https://github.com/minimistjs/minimist/pull/12)
+- [Fix] opt.string works with multiple aliases [`#10`](https://github.com/minimistjs/minimist/pull/10)
+
+### Fixed
+
+- [Fix] Fix long option followed by single dash (#17) [`#15`](https://github.com/minimistjs/minimist/issues/15)
+- [Tests] Remove duplicate test (#12) [`#8`](https://github.com/minimistjs/minimist/issues/8)
+- [Fix] opt.string works with multiple aliases (#10) [`#9`](https://github.com/minimistjs/minimist/issues/9)
+
+### Commits
+
+- [eslint] fix indentation and whitespace [`e5f5067`](https://github.com/minimistjs/minimist/commit/e5f5067259ceeaf0b098d14bec910f87e58708c7)
+- [eslint] more cleanup [`36ac5d0`](https://github.com/minimistjs/minimist/commit/36ac5d0d95e4947d074e5737d94814034ca335d1)
+- [eslint] fix indentation [`34b0f1c`](https://github.com/minimistjs/minimist/commit/34b0f1ccaa45183c3c4f06a91f9b405180a6f982)
+- isConstructorOrProto adapted from PR [`ef9153f`](https://github.com/minimistjs/minimist/commit/ef9153fc52b6cea0744b2239921c5dcae4697f11)
+- [Dev Deps] update `@ljharb/eslint-config`, `aud` [`098873c`](https://github.com/minimistjs/minimist/commit/098873c213cdb7c92e55ae1ef5aa1af3a8192a79)
+- [Dev Deps] add missing `npmignore` dev dep [`3226afa`](https://github.com/minimistjs/minimist/commit/3226afaf09e9d127ca369742437fe6e88f752d6b)
+
+## [v0.2.2](https://github.com/minimistjs/minimist/compare/v0.2.1...v0.2.2) - 2022-10-10
+
+### Commits
+
+- [meta] add `auto-changelog` [`73923d2`](https://github.com/minimistjs/minimist/commit/73923d223553fca08b1ba77e3fbc2a492862ae4c)
+- [actions] add reusable workflows [`d80727d`](https://github.com/minimistjs/minimist/commit/d80727df77bfa9e631044d7f16368d8f09242c91)
+- [eslint] add eslint; rules to enable later are warnings [`48bc06a`](https://github.com/minimistjs/minimist/commit/48bc06a1b41f00e9cdf183db34f7a51ba70e98d4)
+- [readme] rename and add badges [`5df0fe4`](https://github.com/minimistjs/minimist/commit/5df0fe49211bd09a3636f8686a7cb3012c3e98f0)
+- [Dev Deps] switch from `covert` to `nyc` [`a48b128`](https://github.com/minimistjs/minimist/commit/a48b128fdb8d427dfb20a15273f83e38d97bef07)
+- [Dev Deps] update `covert`, `tape`; remove unnecessary `tap` [`f0fb958`](https://github.com/minimistjs/minimist/commit/f0fb958e9a1fe980cdffc436a211b0bda58f621b)
+- [meta] create FUNDING.yml; add `funding` in package.json [`3639e0c`](https://github.com/minimistjs/minimist/commit/3639e0c819359a366387e425ab6eabf4c78d3caa)
+- [meta] use `npmignore` to autogenerate an npmignore file [`be2e038`](https://github.com/minimistjs/minimist/commit/be2e038c342d8333b32f0fde67a0026b79c8150e)
+- Only apps should have lockfiles [`282b570`](https://github.com/minimistjs/minimist/commit/282b570e7489d01b03f2d6d3dabf79cd3e5f84cf)
+- [meta] add `safe-publish-latest` [`4b927de`](https://github.com/minimistjs/minimist/commit/4b927de696d561c636b4f43bf49d4597cb36d6d6)
+- [Tests] add `aud` in `posttest` [`b32d9bd`](https://github.com/minimistjs/minimist/commit/b32d9bd0ab340f4e9f8c3a97ff2a4424f25fab8c)
+- [meta] update repo URLs [`f9fdfc0`](https://github.com/minimistjs/minimist/commit/f9fdfc032c54884d9a9996a390c63cd0719bbe1a)
+
+## [v0.2.1](https://github.com/minimistjs/minimist/compare/v0.2.0...v0.2.1) - 2020-03-12
+
+## [v0.2.0](https://github.com/minimistjs/minimist/compare/v0.1.0...v0.2.0) - 2014-06-19
+
+### Commits
+
+- support all-boolean mode [`450a97f`](https://github.com/minimistjs/minimist/commit/450a97f6e2bc85c7a4a13185c19a818d9a5ebe69)
+
+## [v0.1.0](https://github.com/minimistjs/minimist/compare/v0.0.10...v0.1.0) - 2014-05-12
+
+### Commits
+
+- Provide a mechanism to segregate -- arguments [`ce4a1e6`](https://github.com/minimistjs/minimist/commit/ce4a1e63a7e8d5ab88d2a3768adefa6af98a445a)
+- documented argv['--'] [`14db0e6`](https://github.com/minimistjs/minimist/commit/14db0e6dbc6d2b9e472adaa54dad7004b364634f)
+- Adding a test-case for notFlags segregation [`715c1e3`](https://github.com/minimistjs/minimist/commit/715c1e3714be223f998f6c537af6b505f0236c16)
+
+## [v0.0.10](https://github.com/minimistjs/minimist/compare/v0.0.9...v0.0.10) - 2014-05-11
+
+### Commits
+
+- dedicated boolean test [`46e448f`](https://github.com/minimistjs/minimist/commit/46e448f9f513cfeb2bcc8b688b9b47ba1e515c2b)
+- dedicated num test [`9bf2d36`](https://github.com/minimistjs/minimist/commit/9bf2d36f1d3b8795be90b8f7de0a937f098aa394)
+- aliased values treated as strings [`1ab743b`](https://github.com/minimistjs/minimist/commit/1ab743bad4484d69f1259bed42f9531de01119de)
+- cover the case of already numbers, at 100% coverage [`b2bb044`](https://github.com/minimistjs/minimist/commit/b2bb04436599d77a2ce029e8e555e25b3aa55d13)
+- another test for higher coverage [`3662624`](https://github.com/minimistjs/minimist/commit/3662624be976d5489d486a856849c048d13be903)
+
+## [v0.0.9](https://github.com/minimistjs/minimist/compare/v0.0.8...v0.0.9) - 2014-05-08
+
+### Commits
+
+- Eliminate `longest` fn. [`824f642`](https://github.com/minimistjs/minimist/commit/824f642038d1b02ede68b6261d1d65163390929a)
+
+## [v0.0.8](https://github.com/minimistjs/minimist/compare/v0.0.7...v0.0.8) - 2014-02-20
+
+### Commits
+
+- return '' if flag is string and empty [`fa63ed4`](https://github.com/minimistjs/minimist/commit/fa63ed4651a4ef4eefddce34188e0d98d745a263)
+- handle joined single letters [`66c248f`](https://github.com/minimistjs/minimist/commit/66c248f0241d4d421d193b022e9e365f11178534)
+
+## [v0.0.7](https://github.com/minimistjs/minimist/compare/v0.0.6...v0.0.7) - 2014-02-08
+
+### Commits
+
+- another swap of .test for .match [`d1da408`](https://github.com/minimistjs/minimist/commit/d1da40819acbe846d89a5c02721211e3c1260dde)
+
+## [v0.0.6](https://github.com/minimistjs/minimist/compare/v0.0.5...v0.0.6) - 2014-02-08
+
+### Commits
+
+- use .test() instead of .match() to not crash on non-string values in the arguments array [`7e0d1ad`](https://github.com/minimistjs/minimist/commit/7e0d1add8c9e5b9b20a4d3d0f9a94d824c578da1)
+
+## [v0.0.5](https://github.com/minimistjs/minimist/compare/v0.0.4...v0.0.5) - 2013-09-18
+
+### Commits
+
+- Improve '--' handling. [`b11822c`](https://github.com/minimistjs/minimist/commit/b11822c09cc9d2460f30384d12afc0b953c037a4)
+
+## [v0.0.4](https://github.com/minimistjs/minimist/compare/v0.0.3...v0.0.4) - 2013-09-17
+
+## [v0.0.3](https://github.com/minimistjs/minimist/compare/v0.0.2...v0.0.3) - 2013-09-12
+
+### Commits
+
+- failing test for single dash preceeding a double dash [`b465514`](https://github.com/minimistjs/minimist/commit/b465514b82c9ae28972d714facd951deb2ad762b)
+- fix for the dot test [`6a095f1`](https://github.com/minimistjs/minimist/commit/6a095f1d364c8fab2d6753d2291a0649315d297a)
+
+## [v0.0.2](https://github.com/minimistjs/minimist/compare/v0.0.1...v0.0.2) - 2013-08-28
+
+### Commits
+
+- allow dotted aliases & defaults [`321c33e`](https://github.com/minimistjs/minimist/commit/321c33e755485faaeb44eeb1c05d33b2e0a5a7c4)
+- use a better version of ff [`e40f611`](https://github.com/minimistjs/minimist/commit/e40f61114cf7be6f7947f7b3eed345853a67dbbb)
+
+## [v0.0.1](https://github.com/minimistjs/minimist/compare/v0.0.0...v0.0.1) - 2013-06-25
+
+### Commits
+
+- remove trailing commas [`6ff0fa0`](https://github.com/minimistjs/minimist/commit/6ff0fa055064f15dbe06d50b89d5173a6796e1db)
+
+## v0.0.0 - 2013-06-25
+
+### Commits
+
+- half of the parse test ported [`3079326`](https://github.com/minimistjs/minimist/commit/307932601325087de6cf94188eb798ffc4f3088a)
+- stripped down code and a passing test from optimist [`7cced88`](https://github.com/minimistjs/minimist/commit/7cced88d82e399d1a03ed23eb667f04d3f320d10)
+- ported parse tests completely over [`9448754`](https://github.com/minimistjs/minimist/commit/944875452e0820df6830b1408c26a0f7d3e1db04)
+- docs, package.json [`a5bf46a`](https://github.com/minimistjs/minimist/commit/a5bf46ac9bb3bd114a9c340276c62c1091e538d5)
+- move more short tests into short.js [`503edb5`](https://github.com/minimistjs/minimist/commit/503edb5c41d89c0d40831ee517154fc13b0f18b9)
+- default bool test was wrong, not the code [`1b9f5db`](https://github.com/minimistjs/minimist/commit/1b9f5db4741b49962846081b68518de824992097)
+- passing long tests ripped out of parse.js [`7972c4a`](https://github.com/minimistjs/minimist/commit/7972c4aff1f4803079e1668006658e2a761a0428)
+- badges [`84c0370`](https://github.com/minimistjs/minimist/commit/84c037063664d42878aace715fe6572ce01b6f3b)
+- all the tests now ported, some failures [`64239ed`](https://github.com/minimistjs/minimist/commit/64239edfe92c711c4eb0da254fcdfad2a5fdb605)
+- failing short test [`f8a5341`](https://github.com/minimistjs/minimist/commit/f8a534112dd1138d2fad722def56a848480c446f)
+- fixed the numeric test [`6b034f3`](https://github.com/minimistjs/minimist/commit/6b034f37c79342c60083ed97fd222e16928aac51)
diff --git a/node_modules/minimist/LICENSE b/node_modules/minimist/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..ee27ba4b4412b0e4a05af5e3d8a005bc6681fdf3
--- /dev/null
+++ b/node_modules/minimist/LICENSE
@@ -0,0 +1,18 @@
+This software is released under the MIT license:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/minimist/README.md b/node_modules/minimist/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..74da3234b4844a2d381a0c6f29f893beee5591bd
--- /dev/null
+++ b/node_modules/minimist/README.md
@@ -0,0 +1,121 @@
+# minimist <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
+
+[![github actions][actions-image]][actions-url]
+[![coverage][codecov-image]][codecov-url]
+[![License][license-image]][license-url]
+[![Downloads][downloads-image]][downloads-url]
+
+[![npm badge][npm-badge-png]][package-url]
+
+parse argument options
+
+This module is the guts of optimist's argument parser without all the
+fanciful decoration.
+
+# example
+
+``` js
+var argv = require('minimist')(process.argv.slice(2));
+console.log(argv);
+```
+
+```
+$ node example/parse.js -a beep -b boop
+{ _: [], a: 'beep', b: 'boop' }
+```
+
+```
+$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
+{
+	_: ['foo', 'bar', 'baz'],
+	x: 3,
+	y: 4,
+	n: 5,
+	a: true,
+	b: true,
+	c: true,
+	beep: 'boop'
+}
+```
+
+# security
+
+Previous versions had a prototype pollution bug that could cause privilege
+escalation in some circumstances when handling untrusted user input.
+
+Please use version 1.2.6 or later:
+
+* https://security.snyk.io/vuln/SNYK-JS-MINIMIST-2429795 (version <=1.2.5)
+* https://snyk.io/vuln/SNYK-JS-MINIMIST-559764 (version <=1.2.3)
+
+# methods
+
+``` js
+var parseArgs = require('minimist')
+```
+
+## var argv = parseArgs(args, opts={})
+
+Return an argument object `argv` populated with the array arguments from `args`.
+
+`argv._` contains all the arguments that didn't have an option associated with
+them.
+
+Numeric-looking arguments will be returned as numbers unless `opts.string` or
+`opts.boolean` is set for that argument name.
+
+Any arguments after `'--'` will not be parsed and will end up in `argv._`.
+
+options can be:
+
+* `opts.string` - a string or array of strings argument names to always treat as
+strings
+* `opts.boolean` - a boolean, string or array of strings to always treat as
+booleans. if `true` will treat all double hyphenated arguments without equal signs
+as boolean (e.g. affects `--foo`, not `-f` or `--foo=bar`)
+* `opts.alias` - an object mapping string names to strings or arrays of string
+argument names to use as aliases
+* `opts.default` - an object mapping string argument names to default values
+* `opts.stopEarly` - when true, populate `argv._` with everything after the
+first non-option
+* `opts['--']` - when true, populate `argv._` with everything before the `--`
+and `argv['--']` with everything after the `--`. Here's an example:
+
+  ```
+  > require('./')('one two three -- four five --six'.split(' '), { '--': true })
+  {
+    _: ['one', 'two', 'three'],
+    '--': ['four', 'five', '--six']
+  }
+  ```
+
+  Note that with `opts['--']` set, parsing for arguments still stops after the
+  `--`.
+
+* `opts.unknown` - a function which is invoked with a command line parameter not
+defined in the `opts` configuration object. If the function returns `false`, the
+unknown option is not added to `argv`.
+
+# install
+
+With [npm](https://npmjs.org) do:
+
+```
+npm install minimist
+```
+
+# license
+
+MIT
+
+[package-url]: https://npmjs.org/package/minimist
+[npm-version-svg]: https://versionbadg.es/minimistjs/minimist.svg
+[npm-badge-png]: https://nodei.co/npm/minimist.png?downloads=true&stars=true
+[license-image]: https://img.shields.io/npm/l/minimist.svg
+[license-url]: LICENSE
+[downloads-image]: https://img.shields.io/npm/dm/minimist.svg
+[downloads-url]: https://npm-stat.com/charts.html?package=minimist
+[codecov-image]: https://codecov.io/gh/minimistjs/minimist/branch/main/graphs/badge.svg
+[codecov-url]: https://app.codecov.io/gh/minimistjs/minimist/
+[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/minimistjs/minimist
+[actions-url]: https://github.com/minimistjs/minimist/actions
diff --git a/node_modules/minimist/example/parse.js b/node_modules/minimist/example/parse.js
new file mode 100644
index 0000000000000000000000000000000000000000..9d90ffb2642b4caddde1ec6fb0cff2e78192bb09
--- /dev/null
+++ b/node_modules/minimist/example/parse.js
@@ -0,0 +1,4 @@
+'use strict';
+
+var argv = require('../')(process.argv.slice(2));
+console.log(argv);
diff --git a/node_modules/minimist/index.js b/node_modules/minimist/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..f020f3940e129c361dc89226efaf8775a4af8752
--- /dev/null
+++ b/node_modules/minimist/index.js
@@ -0,0 +1,263 @@
+'use strict';
+
+function hasKey(obj, keys) {
+	var o = obj;
+	keys.slice(0, -1).forEach(function (key) {
+		o = o[key] || {};
+	});
+
+	var key = keys[keys.length - 1];
+	return key in o;
+}
+
+function isNumber(x) {
+	if (typeof x === 'number') { return true; }
+	if ((/^0x[0-9a-f]+$/i).test(x)) { return true; }
+	return (/^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/).test(x);
+}
+
+function isConstructorOrProto(obj, key) {
+	return (key === 'constructor' && typeof obj[key] === 'function') || key === '__proto__';
+}
+
+module.exports = function (args, opts) {
+	if (!opts) { opts = {}; }
+
+	var flags = {
+		bools: {},
+		strings: {},
+		unknownFn: null,
+	};
+
+	if (typeof opts.unknown === 'function') {
+		flags.unknownFn = opts.unknown;
+	}
+
+	if (typeof opts.boolean === 'boolean' && opts.boolean) {
+		flags.allBools = true;
+	} else {
+		[].concat(opts.boolean).filter(Boolean).forEach(function (key) {
+			flags.bools[key] = true;
+		});
+	}
+
+	var aliases = {};
+
+	function aliasIsBoolean(key) {
+		return aliases[key].some(function (x) {
+			return flags.bools[x];
+		});
+	}
+
+	Object.keys(opts.alias || {}).forEach(function (key) {
+		aliases[key] = [].concat(opts.alias[key]);
+		aliases[key].forEach(function (x) {
+			aliases[x] = [key].concat(aliases[key].filter(function (y) {
+				return x !== y;
+			}));
+		});
+	});
+
+	[].concat(opts.string).filter(Boolean).forEach(function (key) {
+		flags.strings[key] = true;
+		if (aliases[key]) {
+			[].concat(aliases[key]).forEach(function (k) {
+				flags.strings[k] = true;
+			});
+		}
+	});
+
+	var defaults = opts.default || {};
+
+	var argv = { _: [] };
+
+	function argDefined(key, arg) {
+		return (flags.allBools && (/^--[^=]+$/).test(arg))
+			|| flags.strings[key]
+			|| flags.bools[key]
+			|| aliases[key];
+	}
+
+	function setKey(obj, keys, value) {
+		var o = obj;
+		for (var i = 0; i < keys.length - 1; i++) {
+			var key = keys[i];
+			if (isConstructorOrProto(o, key)) { return; }
+			if (o[key] === undefined) { o[key] = {}; }
+			if (
+				o[key] === Object.prototype
+				|| o[key] === Number.prototype
+				|| o[key] === String.prototype
+			) {
+				o[key] = {};
+			}
+			if (o[key] === Array.prototype) { o[key] = []; }
+			o = o[key];
+		}
+
+		var lastKey = keys[keys.length - 1];
+		if (isConstructorOrProto(o, lastKey)) { return; }
+		if (
+			o === Object.prototype
+			|| o === Number.prototype
+			|| o === String.prototype
+		) {
+			o = {};
+		}
+		if (o === Array.prototype) { o = []; }
+		if (o[lastKey] === undefined || flags.bools[lastKey] || typeof o[lastKey] === 'boolean') {
+			o[lastKey] = value;
+		} else if (Array.isArray(o[lastKey])) {
+			o[lastKey].push(value);
+		} else {
+			o[lastKey] = [o[lastKey], value];
+		}
+	}
+
+	function setArg(key, val, arg) {
+		if (arg && flags.unknownFn && !argDefined(key, arg)) {
+			if (flags.unknownFn(arg) === false) { return; }
+		}
+
+		var value = !flags.strings[key] && isNumber(val)
+			? Number(val)
+			: val;
+		setKey(argv, key.split('.'), value);
+
+		(aliases[key] || []).forEach(function (x) {
+			setKey(argv, x.split('.'), value);
+		});
+	}
+
+	Object.keys(flags.bools).forEach(function (key) {
+		setArg(key, defaults[key] === undefined ? false : defaults[key]);
+	});
+
+	var notFlags = [];
+
+	if (args.indexOf('--') !== -1) {
+		notFlags = args.slice(args.indexOf('--') + 1);
+		args = args.slice(0, args.indexOf('--'));
+	}
+
+	for (var i = 0; i < args.length; i++) {
+		var arg = args[i];
+		var key;
+		var next;
+
+		if ((/^--.+=/).test(arg)) {
+			// Using [\s\S] instead of . because js doesn't support the
+			// 'dotall' regex modifier. See:
+			// http://stackoverflow.com/a/1068308/13216
+			var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
+			key = m[1];
+			var value = m[2];
+			if (flags.bools[key]) {
+				value = value !== 'false';
+			}
+			setArg(key, value, arg);
+		} else if ((/^--no-.+/).test(arg)) {
+			key = arg.match(/^--no-(.+)/)[1];
+			setArg(key, false, arg);
+		} else if ((/^--.+/).test(arg)) {
+			key = arg.match(/^--(.+)/)[1];
+			next = args[i + 1];
+			if (
+				next !== undefined
+				&& !(/^(-|--)[^-]/).test(next)
+				&& !flags.bools[key]
+				&& !flags.allBools
+				&& (aliases[key] ? !aliasIsBoolean(key) : true)
+			) {
+				setArg(key, next, arg);
+				i += 1;
+			} else if ((/^(true|false)$/).test(next)) {
+				setArg(key, next === 'true', arg);
+				i += 1;
+			} else {
+				setArg(key, flags.strings[key] ? '' : true, arg);
+			}
+		} else if ((/^-[^-]+/).test(arg)) {
+			var letters = arg.slice(1, -1).split('');
+
+			var broken = false;
+			for (var j = 0; j < letters.length; j++) {
+				next = arg.slice(j + 2);
+
+				if (next === '-') {
+					setArg(letters[j], next, arg);
+					continue;
+				}
+
+				if ((/[A-Za-z]/).test(letters[j]) && next[0] === '=') {
+					setArg(letters[j], next.slice(1), arg);
+					broken = true;
+					break;
+				}
+
+				if (
+					(/[A-Za-z]/).test(letters[j])
+					&& (/-?\d+(\.\d*)?(e-?\d+)?$/).test(next)
+				) {
+					setArg(letters[j], next, arg);
+					broken = true;
+					break;
+				}
+
+				if (letters[j + 1] && letters[j + 1].match(/\W/)) {
+					setArg(letters[j], arg.slice(j + 2), arg);
+					broken = true;
+					break;
+				} else {
+					setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg);
+				}
+			}
+
+			key = arg.slice(-1)[0];
+			if (!broken && key !== '-') {
+				if (
+					args[i + 1]
+					&& !(/^(-|--)[^-]/).test(args[i + 1])
+					&& !flags.bools[key]
+					&& (aliases[key] ? !aliasIsBoolean(key) : true)
+				) {
+					setArg(key, args[i + 1], arg);
+					i += 1;
+				} else if (args[i + 1] && (/^(true|false)$/).test(args[i + 1])) {
+					setArg(key, args[i + 1] === 'true', arg);
+					i += 1;
+				} else {
+					setArg(key, flags.strings[key] ? '' : true, arg);
+				}
+			}
+		} else {
+			if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
+				argv._.push(flags.strings._ || !isNumber(arg) ? arg : Number(arg));
+			}
+			if (opts.stopEarly) {
+				argv._.push.apply(argv._, args.slice(i + 1));
+				break;
+			}
+		}
+	}
+
+	Object.keys(defaults).forEach(function (k) {
+		if (!hasKey(argv, k.split('.'))) {
+			setKey(argv, k.split('.'), defaults[k]);
+
+			(aliases[k] || []).forEach(function (x) {
+				setKey(argv, x.split('.'), defaults[k]);
+			});
+		}
+	});
+
+	if (opts['--']) {
+		argv['--'] = notFlags.slice();
+	} else {
+		notFlags.forEach(function (k) {
+			argv._.push(k);
+		});
+	}
+
+	return argv;
+};
diff --git a/node_modules/minimist/package.json b/node_modules/minimist/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..c10a3344411197a716883caad07f0319f5d69b89
--- /dev/null
+++ b/node_modules/minimist/package.json
@@ -0,0 +1,75 @@
+{
+	"name": "minimist",
+	"version": "1.2.8",
+	"description": "parse argument options",
+	"main": "index.js",
+	"devDependencies": {
+		"@ljharb/eslint-config": "^21.0.1",
+		"aud": "^2.0.2",
+		"auto-changelog": "^2.4.0",
+		"eslint": "=8.8.0",
+		"in-publish": "^2.0.1",
+		"npmignore": "^0.3.0",
+		"nyc": "^10.3.2",
+		"safe-publish-latest": "^2.0.0",
+		"tape": "^5.6.3"
+	},
+	"scripts": {
+		"prepack": "npmignore --auto --commentLines=auto",
+		"prepublishOnly": "safe-publish-latest",
+		"prepublish": "not-in-publish || npm run prepublishOnly",
+		"lint": "eslint --ext=js,mjs .",
+		"pretest": "npm run lint",
+		"tests-only": "nyc tape 'test/**/*.js'",
+		"test": "npm run tests-only",
+		"posttest": "aud --production",
+		"version": "auto-changelog && git add CHANGELOG.md",
+		"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
+	},
+	"testling": {
+		"files": "test/*.js",
+		"browsers": [
+			"ie/6..latest",
+			"ff/5",
+			"firefox/latest",
+			"chrome/10",
+			"chrome/latest",
+			"safari/5.1",
+			"safari/latest",
+			"opera/12"
+		]
+	},
+	"repository": {
+		"type": "git",
+		"url": "git://github.com/minimistjs/minimist.git"
+	},
+	"homepage": "https://github.com/minimistjs/minimist",
+	"keywords": [
+		"argv",
+		"getopt",
+		"parser",
+		"optimist"
+	],
+	"author": {
+		"name": "James Halliday",
+		"email": "mail@substack.net",
+		"url": "http://substack.net"
+	},
+	"funding": {
+		"url": "https://github.com/sponsors/ljharb"
+	},
+	"license": "MIT",
+	"auto-changelog": {
+		"output": "CHANGELOG.md",
+		"template": "keepachangelog",
+		"unreleased": false,
+		"commitLimit": false,
+		"backfillLimit": false,
+		"hideCredit": true
+	},
+	"publishConfig": {
+		"ignore": [
+			".github/workflows"
+		]
+	}
+}
diff --git a/node_modules/minimist/test/all_bool.js b/node_modules/minimist/test/all_bool.js
new file mode 100644
index 0000000000000000000000000000000000000000..befa0c99769080972260dac9e4a77630857000f2
--- /dev/null
+++ b/node_modules/minimist/test/all_bool.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('flag boolean true (default all --args to boolean)', function (t) {
+	var argv = parse(['moo', '--honk', 'cow'], {
+		boolean: true,
+	});
+
+	t.deepEqual(argv, {
+		honk: true,
+		_: ['moo', 'cow'],
+	});
+
+	t.deepEqual(typeof argv.honk, 'boolean');
+	t.end();
+});
+
+test('flag boolean true only affects double hyphen arguments without equals signs', function (t) {
+	var argv = parse(['moo', '--honk', 'cow', '-p', '55', '--tacos=good'], {
+		boolean: true,
+	});
+
+	t.deepEqual(argv, {
+		honk: true,
+		tacos: 'good',
+		p: 55,
+		_: ['moo', 'cow'],
+	});
+
+	t.deepEqual(typeof argv.honk, 'boolean');
+	t.end();
+});
diff --git a/node_modules/minimist/test/bool.js b/node_modules/minimist/test/bool.js
new file mode 100644
index 0000000000000000000000000000000000000000..e58d47e442ce127bfe5703b6b64d14c3e4511223
--- /dev/null
+++ b/node_modules/minimist/test/bool.js
@@ -0,0 +1,177 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('flag boolean default false', function (t) {
+	var argv = parse(['moo'], {
+		boolean: ['t', 'verbose'],
+		default: { verbose: false, t: false },
+	});
+
+	t.deepEqual(argv, {
+		verbose: false,
+		t: false,
+		_: ['moo'],
+	});
+
+	t.deepEqual(typeof argv.verbose, 'boolean');
+	t.deepEqual(typeof argv.t, 'boolean');
+	t.end();
+
+});
+
+test('boolean groups', function (t) {
+	var argv = parse(['-x', '-z', 'one', 'two', 'three'], {
+		boolean: ['x', 'y', 'z'],
+	});
+
+	t.deepEqual(argv, {
+		x: true,
+		y: false,
+		z: true,
+		_: ['one', 'two', 'three'],
+	});
+
+	t.deepEqual(typeof argv.x, 'boolean');
+	t.deepEqual(typeof argv.y, 'boolean');
+	t.deepEqual(typeof argv.z, 'boolean');
+	t.end();
+});
+test('boolean and alias with chainable api', function (t) {
+	var aliased = ['-h', 'derp'];
+	var regular = ['--herp', 'derp'];
+	var aliasedArgv = parse(aliased, {
+		boolean: 'herp',
+		alias: { h: 'herp' },
+	});
+	var propertyArgv = parse(regular, {
+		boolean: 'herp',
+		alias: { h: 'herp' },
+	});
+	var expected = {
+		herp: true,
+		h: true,
+		_: ['derp'],
+	};
+
+	t.same(aliasedArgv, expected);
+	t.same(propertyArgv, expected);
+	t.end();
+});
+
+test('boolean and alias with options hash', function (t) {
+	var aliased = ['-h', 'derp'];
+	var regular = ['--herp', 'derp'];
+	var opts = {
+		alias: { h: 'herp' },
+		boolean: 'herp',
+	};
+	var aliasedArgv = parse(aliased, opts);
+	var propertyArgv = parse(regular, opts);
+	var expected = {
+		herp: true,
+		h: true,
+		_: ['derp'],
+	};
+	t.same(aliasedArgv, expected);
+	t.same(propertyArgv, expected);
+	t.end();
+});
+
+test('boolean and alias array with options hash', function (t) {
+	var aliased = ['-h', 'derp'];
+	var regular = ['--herp', 'derp'];
+	var alt = ['--harp', 'derp'];
+	var opts = {
+		alias: { h: ['herp', 'harp'] },
+		boolean: 'h',
+	};
+	var aliasedArgv = parse(aliased, opts);
+	var propertyArgv = parse(regular, opts);
+	var altPropertyArgv = parse(alt, opts);
+	var expected = {
+		harp: true,
+		herp: true,
+		h: true,
+		_: ['derp'],
+	};
+	t.same(aliasedArgv, expected);
+	t.same(propertyArgv, expected);
+	t.same(altPropertyArgv, expected);
+	t.end();
+});
+
+test('boolean and alias using explicit true', function (t) {
+	var aliased = ['-h', 'true'];
+	var regular = ['--herp', 'true'];
+	var opts = {
+		alias: { h: 'herp' },
+		boolean: 'h',
+	};
+	var aliasedArgv = parse(aliased, opts);
+	var propertyArgv = parse(regular, opts);
+	var expected = {
+		herp: true,
+		h: true,
+		_: [],
+	};
+
+	t.same(aliasedArgv, expected);
+	t.same(propertyArgv, expected);
+	t.end();
+});
+
+// regression, see https://github.com/substack/node-optimist/issues/71
+test('boolean and --x=true', function (t) {
+	var parsed = parse(['--boool', '--other=true'], {
+		boolean: 'boool',
+	});
+
+	t.same(parsed.boool, true);
+	t.same(parsed.other, 'true');
+
+	parsed = parse(['--boool', '--other=false'], {
+		boolean: 'boool',
+	});
+
+	t.same(parsed.boool, true);
+	t.same(parsed.other, 'false');
+	t.end();
+});
+
+test('boolean --boool=true', function (t) {
+	var parsed = parse(['--boool=true'], {
+		default: {
+			boool: false,
+		},
+		boolean: ['boool'],
+	});
+
+	t.same(parsed.boool, true);
+	t.end();
+});
+
+test('boolean --boool=false', function (t) {
+	var parsed = parse(['--boool=false'], {
+		default: {
+			boool: true,
+		},
+		boolean: ['boool'],
+	});
+
+	t.same(parsed.boool, false);
+	t.end();
+});
+
+test('boolean using something similar to true', function (t) {
+	var opts = { boolean: 'h' };
+	var result = parse(['-h', 'true.txt'], opts);
+	var expected = {
+		h: true,
+		_: ['true.txt'],
+	};
+
+	t.same(result, expected);
+	t.end();
+});
diff --git a/node_modules/minimist/test/dash.js b/node_modules/minimist/test/dash.js
new file mode 100644
index 0000000000000000000000000000000000000000..707881771e275240a0e0d6d4d2fb8d31a564d74f
--- /dev/null
+++ b/node_modules/minimist/test/dash.js
@@ -0,0 +1,43 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('-', function (t) {
+	t.plan(6);
+	t.deepEqual(parse(['-n', '-']), { n: '-', _: [] });
+	t.deepEqual(parse(['--nnn', '-']), { nnn: '-', _: [] });
+	t.deepEqual(parse(['-']), { _: ['-'] });
+	t.deepEqual(parse(['-f-']), { f: '-', _: [] });
+	t.deepEqual(
+		parse(['-b', '-'], { boolean: 'b' }),
+		{ b: true, _: ['-'] }
+	);
+	t.deepEqual(
+		parse(['-s', '-'], { string: 's' }),
+		{ s: '-', _: [] }
+	);
+});
+
+test('-a -- b', function (t) {
+	t.plan(2);
+	t.deepEqual(parse(['-a', '--', 'b']), { a: true, _: ['b'] });
+	t.deepEqual(parse(['--a', '--', 'b']), { a: true, _: ['b'] });
+});
+
+test('move arguments after the -- into their own `--` array', function (t) {
+	t.plan(1);
+	t.deepEqual(
+		parse(['--name', 'John', 'before', '--', 'after'], { '--': true }),
+		{ name: 'John', _: ['before'], '--': ['after'] }
+	);
+});
+
+test('--- option value', function (t) {
+	// A multi-dash value is largely an edge case, but check the behaviour is as expected,
+	// and in particular the same for short option and long option (as made consistent in Jan 2023).
+	t.plan(2);
+	t.deepEqual(parse(['-n', '---']), { n: '---', _: [] });
+	t.deepEqual(parse(['--nnn', '---']), { nnn: '---', _: [] });
+});
+
diff --git a/node_modules/minimist/test/default_bool.js b/node_modules/minimist/test/default_bool.js
new file mode 100644
index 0000000000000000000000000000000000000000..4e9f6250f08ea8e005b66729630660a3db195566
--- /dev/null
+++ b/node_modules/minimist/test/default_bool.js
@@ -0,0 +1,37 @@
+'use strict';
+
+var test = require('tape');
+var parse = require('../');
+
+test('boolean default true', function (t) {
+	var argv = parse([], {
+		boolean: 'sometrue',
+		default: { sometrue: true },
+	});
+	t.equal(argv.sometrue, true);
+	t.end();
+});
+
+test('boolean default false', function (t) {
+	var argv = parse([], {
+		boolean: 'somefalse',
+		default: { somefalse: false },
+	});
+	t.equal(argv.somefalse, false);
+	t.end();
+});
+
+test('boolean default to null', function (t) {
+	var argv = parse([], {
+		boolean: 'maybe',
+		default: { maybe: null },
+	});
+	t.equal(argv.maybe, null);
+
+	var argvLong = parse(['--maybe'], {
+		boolean: 'maybe',
+		default: { maybe: null },
+	});
+	t.equal(argvLong.maybe, true);
+	t.end();
+});
diff --git a/node_modules/minimist/test/dotted.js b/node_modules/minimist/test/dotted.js
new file mode 100644
index 0000000000000000000000000000000000000000..126ff033b4237334be18dafed9f2b4636f684d2d
--- /dev/null
+++ b/node_modules/minimist/test/dotted.js
@@ -0,0 +1,24 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('dotted alias', function (t) {
+	var argv = parse(['--a.b', '22'], { default: { 'a.b': 11 }, alias: { 'a.b': 'aa.bb' } });
+	t.equal(argv.a.b, 22);
+	t.equal(argv.aa.bb, 22);
+	t.end();
+});
+
+test('dotted default', function (t) {
+	var argv = parse('', { default: { 'a.b': 11 }, alias: { 'a.b': 'aa.bb' } });
+	t.equal(argv.a.b, 11);
+	t.equal(argv.aa.bb, 11);
+	t.end();
+});
+
+test('dotted default with no alias', function (t) {
+	var argv = parse('', { default: { 'a.b': 11 } });
+	t.equal(argv.a.b, 11);
+	t.end();
+});
diff --git a/node_modules/minimist/test/kv_short.js b/node_modules/minimist/test/kv_short.js
new file mode 100644
index 0000000000000000000000000000000000000000..6d1b53a7a7ee1fcbeb9b12c9804f83ff90f46ccd
--- /dev/null
+++ b/node_modules/minimist/test/kv_short.js
@@ -0,0 +1,32 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('short -k=v', function (t) {
+	t.plan(1);
+
+	var argv = parse(['-b=123']);
+	t.deepEqual(argv, { b: 123, _: [] });
+});
+
+test('multi short -k=v', function (t) {
+	t.plan(1);
+
+	var argv = parse(['-a=whatever', '-b=robots']);
+	t.deepEqual(argv, { a: 'whatever', b: 'robots', _: [] });
+});
+
+test('short with embedded equals -k=a=b', function (t) {
+	t.plan(1);
+
+	var argv = parse(['-k=a=b']);
+	t.deepEqual(argv, { k: 'a=b', _: [] });
+});
+
+test('short with later equals like -ab=c', function (t) {
+	t.plan(1);
+
+	var argv = parse(['-ab=c']);
+	t.deepEqual(argv, { a: true, b: 'c', _: [] });
+});
diff --git a/node_modules/minimist/test/long.js b/node_modules/minimist/test/long.js
new file mode 100644
index 0000000000000000000000000000000000000000..9fef51f1fa8d9bf8ef9e92ad2ce5742f009ab941
--- /dev/null
+++ b/node_modules/minimist/test/long.js
@@ -0,0 +1,33 @@
+'use strict';
+
+var test = require('tape');
+var parse = require('../');
+
+test('long opts', function (t) {
+	t.deepEqual(
+		parse(['--bool']),
+		{ bool: true, _: [] },
+		'long boolean'
+	);
+	t.deepEqual(
+		parse(['--pow', 'xixxle']),
+		{ pow: 'xixxle', _: [] },
+		'long capture sp'
+	);
+	t.deepEqual(
+		parse(['--pow=xixxle']),
+		{ pow: 'xixxle', _: [] },
+		'long capture eq'
+	);
+	t.deepEqual(
+		parse(['--host', 'localhost', '--port', '555']),
+		{ host: 'localhost', port: 555, _: [] },
+		'long captures sp'
+	);
+	t.deepEqual(
+		parse(['--host=localhost', '--port=555']),
+		{ host: 'localhost', port: 555, _: [] },
+		'long captures eq'
+	);
+	t.end();
+});
diff --git a/node_modules/minimist/test/num.js b/node_modules/minimist/test/num.js
new file mode 100644
index 0000000000000000000000000000000000000000..074393ecaf1705b9a6170c35ad23d55df943f306
--- /dev/null
+++ b/node_modules/minimist/test/num.js
@@ -0,0 +1,38 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('nums', function (t) {
+	var argv = parse([
+		'-x', '1234',
+		'-y', '5.67',
+		'-z', '1e7',
+		'-w', '10f',
+		'--hex', '0xdeadbeef',
+		'789',
+	]);
+	t.deepEqual(argv, {
+		x: 1234,
+		y: 5.67,
+		z: 1e7,
+		w: '10f',
+		hex: 0xdeadbeef,
+		_: [789],
+	});
+	t.deepEqual(typeof argv.x, 'number');
+	t.deepEqual(typeof argv.y, 'number');
+	t.deepEqual(typeof argv.z, 'number');
+	t.deepEqual(typeof argv.w, 'string');
+	t.deepEqual(typeof argv.hex, 'number');
+	t.deepEqual(typeof argv._[0], 'number');
+	t.end();
+});
+
+test('already a number', function (t) {
+	var argv = parse(['-x', 1234, 789]);
+	t.deepEqual(argv, { x: 1234, _: [789] });
+	t.deepEqual(typeof argv.x, 'number');
+	t.deepEqual(typeof argv._[0], 'number');
+	t.end();
+});
diff --git a/node_modules/minimist/test/parse.js b/node_modules/minimist/test/parse.js
new file mode 100644
index 0000000000000000000000000000000000000000..65d9d90927b91baa152a32e1485479307f1acf44
--- /dev/null
+++ b/node_modules/minimist/test/parse.js
@@ -0,0 +1,209 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('parse args', function (t) {
+	t.deepEqual(
+		parse(['--no-moo']),
+		{ moo: false, _: [] },
+		'no'
+	);
+	t.deepEqual(
+		parse(['-v', 'a', '-v', 'b', '-v', 'c']),
+		{ v: ['a', 'b', 'c'], _: [] },
+		'multi'
+	);
+	t.end();
+});
+
+test('comprehensive', function (t) {
+	t.deepEqual(
+		parse([
+			'--name=meowmers', 'bare', '-cats', 'woo',
+			'-h', 'awesome', '--multi=quux',
+			'--key', 'value',
+			'-b', '--bool', '--no-meep', '--multi=baz',
+			'--', '--not-a-flag', 'eek',
+		]),
+		{
+			c: true,
+			a: true,
+			t: true,
+			s: 'woo',
+			h: 'awesome',
+			b: true,
+			bool: true,
+			key: 'value',
+			multi: ['quux', 'baz'],
+			meep: false,
+			name: 'meowmers',
+			_: ['bare', '--not-a-flag', 'eek'],
+		}
+	);
+	t.end();
+});
+
+test('flag boolean', function (t) {
+	var argv = parse(['-t', 'moo'], { boolean: 't' });
+	t.deepEqual(argv, { t: true, _: ['moo'] });
+	t.deepEqual(typeof argv.t, 'boolean');
+	t.end();
+});
+
+test('flag boolean value', function (t) {
+	var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], {
+		boolean: ['t', 'verbose'],
+		default: { verbose: true },
+	});
+
+	t.deepEqual(argv, {
+		verbose: false,
+		t: true,
+		_: ['moo'],
+	});
+
+	t.deepEqual(typeof argv.verbose, 'boolean');
+	t.deepEqual(typeof argv.t, 'boolean');
+	t.end();
+});
+
+test('newlines in params', function (t) {
+	var args = parse(['-s', 'X\nX']);
+	t.deepEqual(args, { _: [], s: 'X\nX' });
+
+	// reproduce in bash:
+	// VALUE="new
+	// line"
+	// node program.js --s="$VALUE"
+	args = parse(['--s=X\nX']);
+	t.deepEqual(args, { _: [], s: 'X\nX' });
+	t.end();
+});
+
+test('strings', function (t) {
+	var s = parse(['-s', '0001234'], { string: 's' }).s;
+	t.equal(s, '0001234');
+	t.equal(typeof s, 'string');
+
+	var x = parse(['-x', '56'], { string: 'x' }).x;
+	t.equal(x, '56');
+	t.equal(typeof x, 'string');
+	t.end();
+});
+
+test('stringArgs', function (t) {
+	var s = parse(['  ', '  '], { string: '_' })._;
+	t.same(s.length, 2);
+	t.same(typeof s[0], 'string');
+	t.same(s[0], '  ');
+	t.same(typeof s[1], 'string');
+	t.same(s[1], '  ');
+	t.end();
+});
+
+test('empty strings', function (t) {
+	var s = parse(['-s'], { string: 's' }).s;
+	t.equal(s, '');
+	t.equal(typeof s, 'string');
+
+	var str = parse(['--str'], { string: 'str' }).str;
+	t.equal(str, '');
+	t.equal(typeof str, 'string');
+
+	var letters = parse(['-art'], {
+		string: ['a', 't'],
+	});
+
+	t.equal(letters.a, '');
+	t.equal(letters.r, true);
+	t.equal(letters.t, '');
+
+	t.end();
+});
+
+test('string and alias', function (t) {
+	var x = parse(['--str', '000123'], {
+		string: 's',
+		alias: { s: 'str' },
+	});
+
+	t.equal(x.str, '000123');
+	t.equal(typeof x.str, 'string');
+	t.equal(x.s, '000123');
+	t.equal(typeof x.s, 'string');
+
+	var y = parse(['-s', '000123'], {
+		string: 'str',
+		alias: { str: 's' },
+	});
+
+	t.equal(y.str, '000123');
+	t.equal(typeof y.str, 'string');
+	t.equal(y.s, '000123');
+	t.equal(typeof y.s, 'string');
+
+	var z = parse(['-s123'], {
+		alias: { str: ['s', 'S'] },
+		string: ['str'],
+	});
+
+	t.deepEqual(
+		z,
+		{ _: [], s: '123', S: '123', str: '123' },
+		'opt.string works with multiple aliases'
+	);
+	t.end();
+});
+
+test('slashBreak', function (t) {
+	t.same(
+		parse(['-I/foo/bar/baz']),
+		{ I: '/foo/bar/baz', _: [] }
+	);
+	t.same(
+		parse(['-xyz/foo/bar/baz']),
+		{ x: true, y: true, z: '/foo/bar/baz', _: [] }
+	);
+	t.end();
+});
+
+test('alias', function (t) {
+	var argv = parse(['-f', '11', '--zoom', '55'], {
+		alias: { z: 'zoom' },
+	});
+	t.equal(argv.zoom, 55);
+	t.equal(argv.z, argv.zoom);
+	t.equal(argv.f, 11);
+	t.end();
+});
+
+test('multiAlias', function (t) {
+	var argv = parse(['-f', '11', '--zoom', '55'], {
+		alias: { z: ['zm', 'zoom'] },
+	});
+	t.equal(argv.zoom, 55);
+	t.equal(argv.z, argv.zoom);
+	t.equal(argv.z, argv.zm);
+	t.equal(argv.f, 11);
+	t.end();
+});
+
+test('nested dotted objects', function (t) {
+	var argv = parse([
+		'--foo.bar', '3', '--foo.baz', '4',
+		'--foo.quux.quibble', '5', '--foo.quux.o_O',
+		'--beep.boop',
+	]);
+
+	t.same(argv.foo, {
+		bar: 3,
+		baz: 4,
+		quux: {
+			quibble: 5,
+			o_O: true,
+		},
+	});
+	t.same(argv.beep, { boop: true });
+	t.end();
+});
diff --git a/node_modules/minimist/test/parse_modified.js b/node_modules/minimist/test/parse_modified.js
new file mode 100644
index 0000000000000000000000000000000000000000..32965d130fbd4f59b9a6e12488cf18901004d1f8
--- /dev/null
+++ b/node_modules/minimist/test/parse_modified.js
@@ -0,0 +1,11 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('parse with modifier functions', function (t) {
+	t.plan(1);
+
+	var argv = parse(['-b', '123'], { boolean: 'b' });
+	t.deepEqual(argv, { b: true, _: [123] });
+});
diff --git a/node_modules/minimist/test/proto.js b/node_modules/minimist/test/proto.js
new file mode 100644
index 0000000000000000000000000000000000000000..6e629dd34ef0942c19c4d124542f5f030c228ae4
--- /dev/null
+++ b/node_modules/minimist/test/proto.js
@@ -0,0 +1,64 @@
+'use strict';
+
+/* eslint no-proto: 0 */
+
+var parse = require('../');
+var test = require('tape');
+
+test('proto pollution', function (t) {
+	var argv = parse(['--__proto__.x', '123']);
+	t.equal({}.x, undefined);
+	t.equal(argv.__proto__.x, undefined);
+	t.equal(argv.x, undefined);
+	t.end();
+});
+
+test('proto pollution (array)', function (t) {
+	var argv = parse(['--x', '4', '--x', '5', '--x.__proto__.z', '789']);
+	t.equal({}.z, undefined);
+	t.deepEqual(argv.x, [4, 5]);
+	t.equal(argv.x.z, undefined);
+	t.equal(argv.x.__proto__.z, undefined);
+	t.end();
+});
+
+test('proto pollution (number)', function (t) {
+	var argv = parse(['--x', '5', '--x.__proto__.z', '100']);
+	t.equal({}.z, undefined);
+	t.equal((4).z, undefined);
+	t.equal(argv.x, 5);
+	t.equal(argv.x.z, undefined);
+	t.end();
+});
+
+test('proto pollution (string)', function (t) {
+	var argv = parse(['--x', 'abc', '--x.__proto__.z', 'def']);
+	t.equal({}.z, undefined);
+	t.equal('...'.z, undefined);
+	t.equal(argv.x, 'abc');
+	t.equal(argv.x.z, undefined);
+	t.end();
+});
+
+test('proto pollution (constructor)', function (t) {
+	var argv = parse(['--constructor.prototype.y', '123']);
+	t.equal({}.y, undefined);
+	t.equal(argv.y, undefined);
+	t.end();
+});
+
+test('proto pollution (constructor function)', function (t) {
+	var argv = parse(['--_.concat.constructor.prototype.y', '123']);
+	function fnToBeTested() {}
+	t.equal(fnToBeTested.y, undefined);
+	t.equal(argv.y, undefined);
+	t.end();
+});
+
+// powered by snyk - https://github.com/backstage/backstage/issues/10343
+test('proto pollution (constructor function) snyk', function (t) {
+	var argv = parse('--_.constructor.constructor.prototype.foo bar'.split(' '));
+	t.equal(function () {}.foo, undefined);
+	t.equal(argv.y, undefined);
+	t.end();
+});
diff --git a/node_modules/minimist/test/short.js b/node_modules/minimist/test/short.js
new file mode 100644
index 0000000000000000000000000000000000000000..4a7b84385bbfdc74314f5e8f7cc4c36afd52b8bd
--- /dev/null
+++ b/node_modules/minimist/test/short.js
@@ -0,0 +1,69 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('numeric short args', function (t) {
+	t.plan(2);
+	t.deepEqual(parse(['-n123']), { n: 123, _: [] });
+	t.deepEqual(
+		parse(['-123', '456']),
+		{ 1: true, 2: true, 3: 456, _: [] }
+	);
+});
+
+test('short', function (t) {
+	t.deepEqual(
+		parse(['-b']),
+		{ b: true, _: [] },
+		'short boolean'
+	);
+	t.deepEqual(
+		parse(['foo', 'bar', 'baz']),
+		{ _: ['foo', 'bar', 'baz'] },
+		'bare'
+	);
+	t.deepEqual(
+		parse(['-cats']),
+		{ c: true, a: true, t: true, s: true, _: [] },
+		'group'
+	);
+	t.deepEqual(
+		parse(['-cats', 'meow']),
+		{ c: true, a: true, t: true, s: 'meow', _: [] },
+		'short group next'
+	);
+	t.deepEqual(
+		parse(['-h', 'localhost']),
+		{ h: 'localhost', _: [] },
+		'short capture'
+	);
+	t.deepEqual(
+		parse(['-h', 'localhost', '-p', '555']),
+		{ h: 'localhost', p: 555, _: [] },
+		'short captures'
+	);
+	t.end();
+});
+
+test('mixed short bool and capture', function (t) {
+	t.same(
+		parse(['-h', 'localhost', '-fp', '555', 'script.js']),
+		{
+			f: true, p: 555, h: 'localhost',
+			_: ['script.js'],
+		}
+	);
+	t.end();
+});
+
+test('short and long', function (t) {
+	t.deepEqual(
+		parse(['-h', 'localhost', '-fp', '555', 'script.js']),
+		{
+			f: true, p: 555, h: 'localhost',
+			_: ['script.js'],
+		}
+	);
+	t.end();
+});
diff --git a/node_modules/minimist/test/stop_early.js b/node_modules/minimist/test/stop_early.js
new file mode 100644
index 0000000000000000000000000000000000000000..52a6a91903028d5230729df63afcdb80d79b0c68
--- /dev/null
+++ b/node_modules/minimist/test/stop_early.js
@@ -0,0 +1,17 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('stops parsing on the first non-option when stopEarly is set', function (t) {
+	var argv = parse(['--aaa', 'bbb', 'ccc', '--ddd'], {
+		stopEarly: true,
+	});
+
+	t.deepEqual(argv, {
+		aaa: 'bbb',
+		_: ['ccc', '--ddd'],
+	});
+
+	t.end();
+});
diff --git a/node_modules/minimist/test/unknown.js b/node_modules/minimist/test/unknown.js
new file mode 100644
index 0000000000000000000000000000000000000000..4f2e0ca447f4ccc2fb7ba4df3876bf45d3f0423a
--- /dev/null
+++ b/node_modules/minimist/test/unknown.js
@@ -0,0 +1,104 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('boolean and alias is not unknown', function (t) {
+	var unknown = [];
+	function unknownFn(arg) {
+		unknown.push(arg);
+		return false;
+	}
+	var aliased = ['-h', 'true', '--derp', 'true'];
+	var regular = ['--herp', 'true', '-d', 'true'];
+	var opts = {
+		alias: { h: 'herp' },
+		boolean: 'h',
+		unknown: unknownFn,
+	};
+	parse(aliased, opts);
+	parse(regular, opts);
+
+	t.same(unknown, ['--derp', '-d']);
+	t.end();
+});
+
+test('flag boolean true any double hyphen argument is not unknown', function (t) {
+	var unknown = [];
+	function unknownFn(arg) {
+		unknown.push(arg);
+		return false;
+	}
+	var argv = parse(['--honk', '--tacos=good', 'cow', '-p', '55'], {
+		boolean: true,
+		unknown: unknownFn,
+	});
+	t.same(unknown, ['--tacos=good', 'cow', '-p']);
+	t.same(argv, {
+		honk: true,
+		_: [],
+	});
+	t.end();
+});
+
+test('string and alias is not unknown', function (t) {
+	var unknown = [];
+	function unknownFn(arg) {
+		unknown.push(arg);
+		return false;
+	}
+	var aliased = ['-h', 'hello', '--derp', 'goodbye'];
+	var regular = ['--herp', 'hello', '-d', 'moon'];
+	var opts = {
+		alias: { h: 'herp' },
+		string: 'h',
+		unknown: unknownFn,
+	};
+	parse(aliased, opts);
+	parse(regular, opts);
+
+	t.same(unknown, ['--derp', '-d']);
+	t.end();
+});
+
+test('default and alias is not unknown', function (t) {
+	var unknown = [];
+	function unknownFn(arg) {
+		unknown.push(arg);
+		return false;
+	}
+	var aliased = ['-h', 'hello'];
+	var regular = ['--herp', 'hello'];
+	var opts = {
+		default: { h: 'bar' },
+		alias: { h: 'herp' },
+		unknown: unknownFn,
+	};
+	parse(aliased, opts);
+	parse(regular, opts);
+
+	t.same(unknown, []);
+	t.end();
+	unknownFn(); // exercise fn for 100% coverage
+});
+
+test('value following -- is not unknown', function (t) {
+	var unknown = [];
+	function unknownFn(arg) {
+		unknown.push(arg);
+		return false;
+	}
+	var aliased = ['--bad', '--', 'good', 'arg'];
+	var opts = {
+		'--': true,
+		unknown: unknownFn,
+	};
+	var argv = parse(aliased, opts);
+
+	t.same(unknown, ['--bad']);
+	t.same(argv, {
+		'--': ['good', 'arg'],
+		_: [],
+	});
+	t.end();
+});
diff --git a/node_modules/minimist/test/whitespace.js b/node_modules/minimist/test/whitespace.js
new file mode 100644
index 0000000000000000000000000000000000000000..4fdaf1d3943f5a16b9d76af9cd7bbc82f2f54b54
--- /dev/null
+++ b/node_modules/minimist/test/whitespace.js
@@ -0,0 +1,10 @@
+'use strict';
+
+var parse = require('../');
+var test = require('tape');
+
+test('whitespace should be whitespace', function (t) {
+	t.plan(1);
+	var x = parse(['-x', '\t']).x;
+	t.equal(x, '\t');
+});
diff --git a/node_modules/multer/LICENSE b/node_modules/multer/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..6c011b18fa16e456f63b662d75047e376306874b
--- /dev/null
+++ b/node_modules/multer/LICENSE
@@ -0,0 +1,17 @@
+Copyright (c) 2014 Hage Yaapa <[http://www.hacksparrow.com](http://www.hacksparrow.com)>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/multer/README.md b/node_modules/multer/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..7f5d08071cae3afc6a9547e2381ec59f13cfc9f8
--- /dev/null
+++ b/node_modules/multer/README.md
@@ -0,0 +1,333 @@
+# Multer [![Build Status](https://travis-ci.org/expressjs/multer.svg?branch=master)](https://travis-ci.org/expressjs/multer) [![NPM version](https://badge.fury.io/js/multer.svg)](https://badge.fury.io/js/multer) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)
+
+Multer is a node.js middleware for handling `multipart/form-data`, which is primarily used for uploading files. It is written
+on top of [busboy](https://github.com/mscdex/busboy) for maximum efficiency.
+
+**NOTE**: Multer will not process any form which is not multipart (`multipart/form-data`).
+
+## Translations 
+
+This README is also available in other languages:
+
+- [Español](https://github.com/expressjs/multer/blob/master/doc/README-es.md) (Spanish)
+- [简体中文](https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md) (Chinese)
+- [한국어](https://github.com/expressjs/multer/blob/master/doc/README-ko.md) (Korean)
+- [Русский язык](https://github.com/expressjs/multer/blob/master/doc/README-ru.md) (Russian)
+- [Việt Nam](https://github.com/expressjs/multer/blob/master/doc/README-vi.md) (Vietnam)
+- [Português](https://github.com/expressjs/multer/blob/master/doc/README-pt-br.md) (Portuguese Brazil)
+
+## Installation
+
+```sh
+$ npm install --save multer
+```
+
+## Usage
+
+Multer adds a `body` object and a `file` or `files` object to the `request` object. The `body` object contains the values of the text fields of the form, the `file` or `files` object contains the files uploaded via the form.
+
+Basic usage example:
+
+Don't forget the `enctype="multipart/form-data"` in your form.
+
+```html
+<form action="/profile" method="post" enctype="multipart/form-data">
+  <input type="file" name="avatar" />
+</form>
+```
+
+```javascript
+const express = require('express')
+const multer  = require('multer')
+const upload = multer({ dest: 'uploads/' })
+
+const app = express()
+
+app.post('/profile', upload.single('avatar'), function (req, res, next) {
+  // req.file is the `avatar` file
+  // req.body will hold the text fields, if there were any
+})
+
+app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
+  // req.files is array of `photos` files
+  // req.body will contain the text fields, if there were any
+})
+
+const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
+app.post('/cool-profile', cpUpload, function (req, res, next) {
+  // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files
+  //
+  // e.g.
+  //  req.files['avatar'][0] -> File
+  //  req.files['gallery'] -> Array
+  //
+  // req.body will contain the text fields, if there were any
+})
+```
+
+In case you need to handle a text-only multipart form, you should use the `.none()` method:
+
+```javascript
+const express = require('express')
+const app = express()
+const multer  = require('multer')
+const upload = multer()
+
+app.post('/profile', upload.none(), function (req, res, next) {
+  // req.body contains the text fields
+})
+```
+
+Here's an example on how multer is used an HTML form. Take special note of the `enctype="multipart/form-data"` and `name="uploaded_file"` fields:
+
+```html
+<form action="/stats" enctype="multipart/form-data" method="post">
+  <div class="form-group">
+    <input type="file" class="form-control-file" name="uploaded_file">
+    <input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers">
+    <input type="submit" value="Get me the stats!" class="btn btn-default">            
+  </div>
+</form>
+```
+
+Then in your javascript file you would add these lines to access both the file and the body. It is important that you use the `name` field value from the form in your upload function. This tells multer which field on the request it should look for the files in. If these fields aren't the same in the HTML form and on your server, your upload will fail:
+
+```javascript
+const multer  = require('multer')
+const upload = multer({ dest: './public/data/uploads/' })
+app.post('/stats', upload.single('uploaded_file'), function (req, res) {
+   // req.file is the name of your file in the form above, here 'uploaded_file'
+   // req.body will hold the text fields, if there were any 
+   console.log(req.file, req.body)
+});
+```
+
+
+
+## API
+
+### File information
+
+Each file contains the following information:
+
+Key | Description | Note
+--- | --- | ---
+`fieldname` | Field name specified in the form |
+`originalname` | Name of the file on the user's computer |
+`encoding` | Encoding type of the file |
+`mimetype` | Mime type of the file |
+`size` | Size of the file in bytes |
+`destination` | The folder to which the file has been saved | `DiskStorage`
+`filename` | The name of the file within the `destination` | `DiskStorage`
+`path` | The full path to the uploaded file | `DiskStorage`
+`buffer` | A `Buffer` of the entire file | `MemoryStorage`
+
+### `multer(opts)`
+
+Multer accepts an options object, the most basic of which is the `dest`
+property, which tells Multer where to upload the files. In case you omit the
+options object, the files will be kept in memory and never written to disk.
+
+By default, Multer will rename the files so as to avoid naming conflicts. The
+renaming function can be customized according to your needs.
+
+The following are the options that can be passed to Multer.
+
+Key | Description
+--- | ---
+`dest` or `storage` | Where to store the files
+`fileFilter` | Function to control which files are accepted
+`limits` | Limits of the uploaded data
+`preservePath` | Keep the full path of files instead of just the base name
+
+In an average web app, only `dest` might be required, and configured as shown in
+the following example.
+
+```javascript
+const upload = multer({ dest: 'uploads/' })
+```
+
+If you want more control over your uploads, you'll want to use the `storage`
+option instead of `dest`. Multer ships with storage engines `DiskStorage`
+and `MemoryStorage`; More engines are available from third parties.
+
+#### `.single(fieldname)`
+
+Accept a single file with the name `fieldname`. The single file will be stored
+in `req.file`.
+
+#### `.array(fieldname[, maxCount])`
+
+Accept an array of files, all with the name `fieldname`. Optionally error out if
+more than `maxCount` files are uploaded. The array of files will be stored in
+`req.files`.
+
+#### `.fields(fields)`
+
+Accept a mix of files, specified by `fields`. An object with arrays of files
+will be stored in `req.files`.
+
+`fields` should be an array of objects with `name` and optionally a `maxCount`.
+Example:
+
+```javascript
+[
+  { name: 'avatar', maxCount: 1 },
+  { name: 'gallery', maxCount: 8 }
+]
+```
+
+#### `.none()`
+
+Accept only text fields. If any file upload is made, error with code
+"LIMIT\_UNEXPECTED\_FILE" will be issued.
+
+#### `.any()`
+
+Accepts all files that comes over the wire. An array of files will be stored in
+`req.files`.
+
+**WARNING:** Make sure that you always handle the files that a user uploads.
+Never add multer as a global middleware since a malicious user could upload
+files to a route that you didn't anticipate. Only use this function on routes
+where you are handling the uploaded files.
+
+### `storage`
+
+#### `DiskStorage`
+
+The disk storage engine gives you full control on storing files to disk.
+
+```javascript
+const storage = multer.diskStorage({
+  destination: function (req, file, cb) {
+    cb(null, '/tmp/my-uploads')
+  },
+  filename: function (req, file, cb) {
+    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
+    cb(null, file.fieldname + '-' + uniqueSuffix)
+  }
+})
+
+const upload = multer({ storage: storage })
+```
+
+There are two options available, `destination` and `filename`. They are both
+functions that determine where the file should be stored.
+
+`destination` is used to determine within which folder the uploaded files should
+be stored. This can also be given as a `string` (e.g. `'/tmp/uploads'`). If no
+`destination` is given, the operating system's default directory for temporary
+files is used.
+
+**Note:** You are responsible for creating the directory when providing
+`destination` as a function. When passing a string, multer will make sure that
+the directory is created for you.
+
+`filename` is used to determine what the file should be named inside the folder.
+If no `filename` is given, each file will be given a random name that doesn't
+include any file extension.
+
+**Note:** Multer will not append any file extension for you, your function
+should return a filename complete with an file extension.
+
+Each function gets passed both the request (`req`) and some information about
+the file (`file`) to aid with the decision.
+
+Note that `req.body` might not have been fully populated yet. It depends on the
+order that the client transmits fields and files to the server.
+
+For understanding the calling convention used in the callback (needing to pass
+null as the first param), refer to
+[Node.js error handling](https://www.joyent.com/node-js/production/design/errors)
+
+#### `MemoryStorage`
+
+The memory storage engine stores the files in memory as `Buffer` objects. It
+doesn't have any options.
+
+```javascript
+const storage = multer.memoryStorage()
+const upload = multer({ storage: storage })
+```
+
+When using memory storage, the file info will contain a field called
+`buffer` that contains the entire file.
+
+**WARNING**: Uploading very large files, or relatively small files in large
+numbers very quickly, can cause your application to run out of memory when
+memory storage is used.
+
+### `limits`
+
+An object specifying the size limits of the following optional properties. Multer passes this object into busboy directly, and the details of the properties can be found on [busboy's page](https://github.com/mscdex/busboy#busboy-methods).
+
+The following integer values are available:
+
+Key | Description | Default
+--- | --- | ---
+`fieldNameSize` | Max field name size | 100 bytes
+`fieldSize` | Max field value size (in bytes) | 1MB
+`fields` | Max number of non-file fields | Infinity
+`fileSize` | For multipart forms, the max file size (in bytes) | Infinity
+`files` | For multipart forms, the max number of file fields | Infinity
+`parts` | For multipart forms, the max number of parts (fields + files) | Infinity
+`headerPairs` | For multipart forms, the max number of header key=>value pairs to parse | 2000
+
+Specifying the limits can help protect your site against denial of service (DoS) attacks.
+
+### `fileFilter`
+
+Set this to a function to control which files should be uploaded and which
+should be skipped. The function should look like this:
+
+```javascript
+function fileFilter (req, file, cb) {
+
+  // The function should call `cb` with a boolean
+  // to indicate if the file should be accepted
+
+  // To reject this file pass `false`, like so:
+  cb(null, false)
+
+  // To accept the file pass `true`, like so:
+  cb(null, true)
+
+  // You can always pass an error if something goes wrong:
+  cb(new Error('I don\'t have a clue!'))
+
+}
+```
+
+## Error handling
+
+When encountering an error, Multer will delegate the error to Express. You can
+display a nice error page using [the standard express way](http://expressjs.com/guide/error-handling.html).
+
+If you want to catch errors specifically from Multer, you can call the
+middleware function by yourself. Also, if you want to catch only [the Multer errors](https://github.com/expressjs/multer/blob/master/lib/multer-error.js), you can use the `MulterError` class that is attached to the `multer` object itself (e.g. `err instanceof multer.MulterError`).
+
+```javascript
+const multer = require('multer')
+const upload = multer().single('avatar')
+
+app.post('/profile', function (req, res) {
+  upload(req, res, function (err) {
+    if (err instanceof multer.MulterError) {
+      // A Multer error occurred when uploading.
+    } else if (err) {
+      // An unknown error occurred when uploading.
+    }
+
+    // Everything went fine.
+  })
+})
+```
+
+## Custom storage engine
+
+For information on how to build your own storage engine, see [Multer Storage Engine](https://github.com/expressjs/multer/blob/master/StorageEngine.md).
+
+## License
+
+[MIT](LICENSE)
diff --git a/node_modules/multer/index.js b/node_modules/multer/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..d5b67eba3a7d9b37840270102aa78486b0e8376b
--- /dev/null
+++ b/node_modules/multer/index.js
@@ -0,0 +1,104 @@
+var makeMiddleware = require('./lib/make-middleware')
+
+var diskStorage = require('./storage/disk')
+var memoryStorage = require('./storage/memory')
+var MulterError = require('./lib/multer-error')
+
+function allowAll (req, file, cb) {
+  cb(null, true)
+}
+
+function Multer (options) {
+  if (options.storage) {
+    this.storage = options.storage
+  } else if (options.dest) {
+    this.storage = diskStorage({ destination: options.dest })
+  } else {
+    this.storage = memoryStorage()
+  }
+
+  this.limits = options.limits
+  this.preservePath = options.preservePath
+  this.fileFilter = options.fileFilter || allowAll
+}
+
+Multer.prototype._makeMiddleware = function (fields, fileStrategy) {
+  function setup () {
+    var fileFilter = this.fileFilter
+    var filesLeft = Object.create(null)
+
+    fields.forEach(function (field) {
+      if (typeof field.maxCount === 'number') {
+        filesLeft[field.name] = field.maxCount
+      } else {
+        filesLeft[field.name] = Infinity
+      }
+    })
+
+    function wrappedFileFilter (req, file, cb) {
+      if ((filesLeft[file.fieldname] || 0) <= 0) {
+        return cb(new MulterError('LIMIT_UNEXPECTED_FILE', file.fieldname))
+      }
+
+      filesLeft[file.fieldname] -= 1
+      fileFilter(req, file, cb)
+    }
+
+    return {
+      limits: this.limits,
+      preservePath: this.preservePath,
+      storage: this.storage,
+      fileFilter: wrappedFileFilter,
+      fileStrategy: fileStrategy
+    }
+  }
+
+  return makeMiddleware(setup.bind(this))
+}
+
+Multer.prototype.single = function (name) {
+  return this._makeMiddleware([{ name: name, maxCount: 1 }], 'VALUE')
+}
+
+Multer.prototype.array = function (name, maxCount) {
+  return this._makeMiddleware([{ name: name, maxCount: maxCount }], 'ARRAY')
+}
+
+Multer.prototype.fields = function (fields) {
+  return this._makeMiddleware(fields, 'OBJECT')
+}
+
+Multer.prototype.none = function () {
+  return this._makeMiddleware([], 'NONE')
+}
+
+Multer.prototype.any = function () {
+  function setup () {
+    return {
+      limits: this.limits,
+      preservePath: this.preservePath,
+      storage: this.storage,
+      fileFilter: this.fileFilter,
+      fileStrategy: 'ARRAY'
+    }
+  }
+
+  return makeMiddleware(setup.bind(this))
+}
+
+function multer (options) {
+  if (options === undefined) {
+    return new Multer({})
+  }
+
+  if (typeof options === 'object' && options !== null) {
+    return new Multer(options)
+  }
+
+  throw new TypeError('Expected object for argument options')
+}
+
+module.exports = multer
+module.exports.diskStorage = diskStorage
+module.exports.memoryStorage = memoryStorage
+module.exports.MulterError = MulterError
diff --git a/node_modules/multer/lib/counter.js b/node_modules/multer/lib/counter.js
new file mode 100644
index 0000000000000000000000000000000000000000..29c410c7b4850d2640fef61629508a534fc98a74
--- /dev/null
+++ b/node_modules/multer/lib/counter.js
@@ -0,0 +1,28 @@
+var EventEmitter = require('events').EventEmitter
+
+function Counter () {
+  EventEmitter.call(this)
+  this.value = 0
+}
+
+Counter.prototype = Object.create(EventEmitter.prototype)
+
+Counter.prototype.increment = function increment () {
+  this.value++
+}
+
+Counter.prototype.decrement = function decrement () {
+  if (--this.value === 0) this.emit('zero')
+}
+
+Counter.prototype.isZero = function isZero () {
+  return (this.value === 0)
+}
+
+Counter.prototype.onceZero = function onceZero (fn) {
+  if (this.isZero()) return fn()
+
+  this.once('zero', fn)
+}
+
+module.exports = Counter
diff --git a/node_modules/multer/lib/file-appender.js b/node_modules/multer/lib/file-appender.js
new file mode 100644
index 0000000000000000000000000000000000000000..1a2c5e76e98c539fc855924111c054d3df943857
--- /dev/null
+++ b/node_modules/multer/lib/file-appender.js
@@ -0,0 +1,67 @@
+var objectAssign = require('object-assign')
+
+function arrayRemove (arr, item) {
+  var idx = arr.indexOf(item)
+  if (~idx) arr.splice(idx, 1)
+}
+
+function FileAppender (strategy, req) {
+  this.strategy = strategy
+  this.req = req
+
+  switch (strategy) {
+    case 'NONE': break
+    case 'VALUE': break
+    case 'ARRAY': req.files = []; break
+    case 'OBJECT': req.files = Object.create(null); break
+    default: throw new Error('Unknown file strategy: ' + strategy)
+  }
+}
+
+FileAppender.prototype.insertPlaceholder = function (file) {
+  var placeholder = {
+    fieldname: file.fieldname
+  }
+
+  switch (this.strategy) {
+    case 'NONE': break
+    case 'VALUE': break
+    case 'ARRAY': this.req.files.push(placeholder); break
+    case 'OBJECT':
+      if (this.req.files[file.fieldname]) {
+        this.req.files[file.fieldname].push(placeholder)
+      } else {
+        this.req.files[file.fieldname] = [placeholder]
+      }
+      break
+  }
+
+  return placeholder
+}
+
+FileAppender.prototype.removePlaceholder = function (placeholder) {
+  switch (this.strategy) {
+    case 'NONE': break
+    case 'VALUE': break
+    case 'ARRAY': arrayRemove(this.req.files, placeholder); break
+    case 'OBJECT':
+      if (this.req.files[placeholder.fieldname].length === 1) {
+        delete this.req.files[placeholder.fieldname]
+      } else {
+        arrayRemove(this.req.files[placeholder.fieldname], placeholder)
+      }
+      break
+  }
+}
+
+FileAppender.prototype.replacePlaceholder = function (placeholder, file) {
+  if (this.strategy === 'VALUE') {
+    this.req.file = file
+    return
+  }
+
+  delete placeholder.fieldname
+  objectAssign(placeholder, file)
+}
+
+module.exports = FileAppender
diff --git a/node_modules/multer/lib/make-middleware.js b/node_modules/multer/lib/make-middleware.js
new file mode 100644
index 0000000000000000000000000000000000000000..6627cf4c335f38bb777b868a13047a145a13d81a
--- /dev/null
+++ b/node_modules/multer/lib/make-middleware.js
@@ -0,0 +1,173 @@
+var is = require('type-is')
+var Busboy = require('busboy')
+var extend = require('xtend')
+var appendField = require('append-field')
+
+var Counter = require('./counter')
+var MulterError = require('./multer-error')
+var FileAppender = require('./file-appender')
+var removeUploadedFiles = require('./remove-uploaded-files')
+
+function makeMiddleware (setup) {
+  return function multerMiddleware (req, res, next) {
+    if (!is(req, ['multipart'])) return next()
+
+    var options = setup()
+
+    var limits = options.limits
+    var storage = options.storage
+    var fileFilter = options.fileFilter
+    var fileStrategy = options.fileStrategy
+    var preservePath = options.preservePath
+
+    req.body = Object.create(null)
+
+    var busboy
+
+    try {
+      busboy = Busboy({ headers: req.headers, limits: limits, preservePath: preservePath })
+    } catch (err) {
+      return next(err)
+    }
+
+    var appender = new FileAppender(fileStrategy, req)
+    var isDone = false
+    var readFinished = false
+    var errorOccured = false
+    var pendingWrites = new Counter()
+    var uploadedFiles = []
+
+    function done (err) {
+      if (isDone) return
+      isDone = true
+      req.unpipe(busboy)
+      busboy.removeAllListeners()
+      next(err)
+    }
+
+    function indicateDone () {
+      if (readFinished && pendingWrites.isZero() && !errorOccured) done()
+    }
+
+    function abortWithError (uploadError) {
+      if (errorOccured) return
+      errorOccured = true
+
+      pendingWrites.onceZero(function () {
+        function remove (file, cb) {
+          storage._removeFile(req, file, cb)
+        }
+
+        removeUploadedFiles(uploadedFiles, remove, function (err, storageErrors) {
+          if (err) return done(err)
+
+          uploadError.storageErrors = storageErrors
+          done(uploadError)
+        })
+      })
+    }
+
+    function abortWithCode (code, optionalField) {
+      abortWithError(new MulterError(code, optionalField))
+    }
+
+    // handle text field data
+    busboy.on('field', function (fieldname, value, { nameTruncated, valueTruncated }) {
+      if (fieldname == null) return abortWithCode('MISSING_FIELD_NAME')
+      if (nameTruncated) return abortWithCode('LIMIT_FIELD_KEY')
+      if (valueTruncated) return abortWithCode('LIMIT_FIELD_VALUE', fieldname)
+
+      // Work around bug in Busboy (https://github.com/mscdex/busboy/issues/6)
+      if (limits && Object.prototype.hasOwnProperty.call(limits, 'fieldNameSize')) {
+        if (fieldname.length > limits.fieldNameSize) return abortWithCode('LIMIT_FIELD_KEY')
+      }
+
+      appendField(req.body, fieldname, value)
+    })
+
+    // handle files
+    busboy.on('file', function (fieldname, fileStream, { filename, encoding, mimeType }) {
+      // don't attach to the files object, if there is no file
+      if (!filename) return fileStream.resume()
+
+      // Work around bug in Busboy (https://github.com/mscdex/busboy/issues/6)
+      if (limits && Object.prototype.hasOwnProperty.call(limits, 'fieldNameSize')) {
+        if (fieldname.length > limits.fieldNameSize) return abortWithCode('LIMIT_FIELD_KEY')
+      }
+
+      var file = {
+        fieldname: fieldname,
+        originalname: filename,
+        encoding: encoding,
+        mimetype: mimeType
+      }
+
+      var placeholder = appender.insertPlaceholder(file)
+
+      fileFilter(req, file, function (err, includeFile) {
+        if (err) {
+          appender.removePlaceholder(placeholder)
+          return abortWithError(err)
+        }
+
+        if (!includeFile) {
+          appender.removePlaceholder(placeholder)
+          return fileStream.resume()
+        }
+
+        var aborting = false
+        pendingWrites.increment()
+
+        Object.defineProperty(file, 'stream', {
+          configurable: true,
+          enumerable: false,
+          value: fileStream
+        })
+
+        fileStream.on('error', function (err) {
+          pendingWrites.decrement()
+          abortWithError(err)
+        })
+
+        fileStream.on('limit', function () {
+          aborting = true
+          abortWithCode('LIMIT_FILE_SIZE', fieldname)
+        })
+
+        storage._handleFile(req, file, function (err, info) {
+          if (aborting) {
+            appender.removePlaceholder(placeholder)
+            uploadedFiles.push(extend(file, info))
+            return pendingWrites.decrement()
+          }
+
+          if (err) {
+            appender.removePlaceholder(placeholder)
+            pendingWrites.decrement()
+            return abortWithError(err)
+          }
+
+          var fileInfo = extend(file, info)
+
+          appender.replacePlaceholder(placeholder, fileInfo)
+          uploadedFiles.push(fileInfo)
+          pendingWrites.decrement()
+          indicateDone()
+        })
+      })
+    })
+
+    busboy.on('error', function (err) { abortWithError(err) })
+    busboy.on('partsLimit', function () { abortWithCode('LIMIT_PART_COUNT') })
+    busboy.on('filesLimit', function () { abortWithCode('LIMIT_FILE_COUNT') })
+    busboy.on('fieldsLimit', function () { abortWithCode('LIMIT_FIELD_COUNT') })
+    busboy.on('close', function () {
+      readFinished = true
+      indicateDone()
+    })
+
+    req.pipe(busboy)
+  }
+}
+
+module.exports = makeMiddleware
diff --git a/node_modules/multer/lib/multer-error.js b/node_modules/multer/lib/multer-error.js
new file mode 100644
index 0000000000000000000000000000000000000000..d56b00e88cc59deb83a5cfec9d7bea3de29400ed
--- /dev/null
+++ b/node_modules/multer/lib/multer-error.js
@@ -0,0 +1,24 @@
+var util = require('util')
+
+var errorMessages = {
+  LIMIT_PART_COUNT: 'Too many parts',
+  LIMIT_FILE_SIZE: 'File too large',
+  LIMIT_FILE_COUNT: 'Too many files',
+  LIMIT_FIELD_KEY: 'Field name too long',
+  LIMIT_FIELD_VALUE: 'Field value too long',
+  LIMIT_FIELD_COUNT: 'Too many fields',
+  LIMIT_UNEXPECTED_FILE: 'Unexpected field',
+  MISSING_FIELD_NAME: 'Field name missing'
+}
+
+function MulterError (code, field) {
+  Error.captureStackTrace(this, this.constructor)
+  this.name = this.constructor.name
+  this.message = errorMessages[code]
+  this.code = code
+  if (field) this.field = field
+}
+
+util.inherits(MulterError, Error)
+
+module.exports = MulterError
diff --git a/node_modules/multer/lib/remove-uploaded-files.js b/node_modules/multer/lib/remove-uploaded-files.js
new file mode 100644
index 0000000000000000000000000000000000000000..f0b16ea506ad69bc1b5f5b37f143a20b21f44569
--- /dev/null
+++ b/node_modules/multer/lib/remove-uploaded-files.js
@@ -0,0 +1,28 @@
+function removeUploadedFiles (uploadedFiles, remove, cb) {
+  var length = uploadedFiles.length
+  var errors = []
+
+  if (length === 0) return cb(null, errors)
+
+  function handleFile (idx) {
+    var file = uploadedFiles[idx]
+
+    remove(file, function (err) {
+      if (err) {
+        err.file = file
+        err.field = file.fieldname
+        errors.push(err)
+      }
+
+      if (idx < length - 1) {
+        handleFile(idx + 1)
+      } else {
+        cb(null, errors)
+      }
+    })
+  }
+
+  handleFile(0)
+}
+
+module.exports = removeUploadedFiles
diff --git a/node_modules/multer/node_modules/.bin/mkdirp b/node_modules/multer/node_modules/.bin/mkdirp
new file mode 100644
index 0000000000000000000000000000000000000000..6ba5765a8cd217d8965731b917977e786e4d97b7
--- /dev/null
+++ b/node_modules/multer/node_modules/.bin/mkdirp
@@ -0,0 +1,12 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../mkdirp/bin/cmd.js" "$@"
+else 
+  exec node  "$basedir/../mkdirp/bin/cmd.js" "$@"
+fi
diff --git a/node_modules/multer/node_modules/.bin/mkdirp.cmd b/node_modules/multer/node_modules/.bin/mkdirp.cmd
new file mode 100644
index 0000000000000000000000000000000000000000..a865dd9f3a2ef7c26f9cb350ee12041578808e79
--- /dev/null
+++ b/node_modules/multer/node_modules/.bin/mkdirp.cmd
@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\mkdirp\bin\cmd.js" %*
diff --git a/node_modules/multer/node_modules/.bin/mkdirp.ps1 b/node_modules/multer/node_modules/.bin/mkdirp.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..911e85466417449a40e584cce49fa18f1c513c3d
--- /dev/null
+++ b/node_modules/multer/node_modules/.bin/mkdirp.ps1
@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../mkdirp/bin/cmd.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../mkdirp/bin/cmd.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../mkdirp/bin/cmd.js" $args
+  } else {
+    & "node$exe"  "$basedir/../mkdirp/bin/cmd.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret
diff --git a/node_modules/multer/node_modules/mkdirp/LICENSE b/node_modules/multer/node_modules/mkdirp/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..432d1aeb01df666910230893f78e0d1ee7635a61
--- /dev/null
+++ b/node_modules/multer/node_modules/mkdirp/LICENSE
@@ -0,0 +1,21 @@
+Copyright 2010 James Halliday (mail@substack.net)
+
+This project is free software released under the MIT/X11 license:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/multer/node_modules/mkdirp/bin/cmd.js b/node_modules/multer/node_modules/mkdirp/bin/cmd.js
new file mode 100644
index 0000000000000000000000000000000000000000..d95de15ae9743fc3b9e901d6fa6e8e1876c630cf
--- /dev/null
+++ b/node_modules/multer/node_modules/mkdirp/bin/cmd.js
@@ -0,0 +1,33 @@
+#!/usr/bin/env node
+
+var mkdirp = require('../');
+var minimist = require('minimist');
+var fs = require('fs');
+
+var argv = minimist(process.argv.slice(2), {
+    alias: { m: 'mode', h: 'help' },
+    string: [ 'mode' ]
+});
+if (argv.help) {
+    fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
+    return;
+}
+
+var paths = argv._.slice();
+var mode = argv.mode ? parseInt(argv.mode, 8) : undefined;
+
+(function next () {
+    if (paths.length === 0) return;
+    var p = paths.shift();
+    
+    if (mode === undefined) mkdirp(p, cb)
+    else mkdirp(p, mode, cb)
+    
+    function cb (err) {
+        if (err) {
+            console.error(err.message);
+            process.exit(1);
+        }
+        else next();
+    }
+})();
diff --git a/node_modules/multer/node_modules/mkdirp/bin/usage.txt b/node_modules/multer/node_modules/mkdirp/bin/usage.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f952aa2c7a979e7ccb2ef81b7b5010b26b6b9e53
--- /dev/null
+++ b/node_modules/multer/node_modules/mkdirp/bin/usage.txt
@@ -0,0 +1,12 @@
+usage: mkdirp [DIR1,DIR2..] {OPTIONS}
+
+  Create each supplied directory including any necessary parent directories that
+  don't yet exist.
+  
+  If the directory already exists, do nothing.
+
+OPTIONS are:
+
+  -m, --mode   If a directory needs to be created, set the mode as an octal
+               permission string.
+
diff --git a/node_modules/multer/node_modules/mkdirp/index.js b/node_modules/multer/node_modules/mkdirp/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..0890ac3bd6a8833dad7e8e8926cb69b3a54a2a47
--- /dev/null
+++ b/node_modules/multer/node_modules/mkdirp/index.js
@@ -0,0 +1,102 @@
+var path = require('path');
+var fs = require('fs');
+var _0777 = parseInt('0777', 8);
+
+module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
+
+function mkdirP (p, opts, f, made) {
+    if (typeof opts === 'function') {
+        f = opts;
+        opts = {};
+    }
+    else if (!opts || typeof opts !== 'object') {
+        opts = { mode: opts };
+    }
+    
+    var mode = opts.mode;
+    var xfs = opts.fs || fs;
+    
+    if (mode === undefined) {
+        mode = _0777
+    }
+    if (!made) made = null;
+    
+    var cb = f || /* istanbul ignore next */ function () {};
+    p = path.resolve(p);
+    
+    xfs.mkdir(p, mode, function (er) {
+        if (!er) {
+            made = made || p;
+            return cb(null, made);
+        }
+        switch (er.code) {
+            case 'ENOENT':
+                /* istanbul ignore if */
+                if (path.dirname(p) === p) return cb(er);
+                mkdirP(path.dirname(p), opts, function (er, made) {
+                    /* istanbul ignore if */
+                    if (er) cb(er, made);
+                    else mkdirP(p, opts, cb, made);
+                });
+                break;
+
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
+                xfs.stat(p, function (er2, stat) {
+                    // if the stat fails, then that's super weird.
+                    // let the original error be the failure reason.
+                    if (er2 || !stat.isDirectory()) cb(er, made)
+                    else cb(null, made);
+                });
+                break;
+        }
+    });
+}
+
+mkdirP.sync = function sync (p, opts, made) {
+    if (!opts || typeof opts !== 'object') {
+        opts = { mode: opts };
+    }
+    
+    var mode = opts.mode;
+    var xfs = opts.fs || fs;
+    
+    if (mode === undefined) {
+        mode = _0777
+    }
+    if (!made) made = null;
+
+    p = path.resolve(p);
+
+    try {
+        xfs.mkdirSync(p, mode);
+        made = made || p;
+    }
+    catch (err0) {
+        switch (err0.code) {
+            case 'ENOENT' :
+                made = sync(path.dirname(p), opts, made);
+                sync(p, opts, made);
+                break;
+
+            // In the case of any other error, just see if there's a dir
+            // there already.  If so, then hooray!  If not, then something
+            // is borked.
+            default:
+                var stat;
+                try {
+                    stat = xfs.statSync(p);
+                }
+                catch (err1) /* istanbul ignore next */ {
+                    throw err0;
+                }
+                /* istanbul ignore if */
+                if (!stat.isDirectory()) throw err0;
+                break;
+        }
+    }
+
+    return made;
+};
diff --git a/node_modules/multer/node_modules/mkdirp/package.json b/node_modules/multer/node_modules/mkdirp/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..951e58da975ee9aca80b40e40ae9a3d1047d1b66
--- /dev/null
+++ b/node_modules/multer/node_modules/mkdirp/package.json
@@ -0,0 +1,33 @@
+{
+  "name": "mkdirp",
+  "description": "Recursively mkdir, like `mkdir -p`",
+  "version": "0.5.6",
+  "publishConfig": {
+    "tag": "legacy"
+  },
+  "author": "James Halliday <mail@substack.net> (http://substack.net)",
+  "main": "index.js",
+  "keywords": [
+    "mkdir",
+    "directory"
+  ],
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/substack/node-mkdirp.git"
+  },
+  "scripts": {
+    "test": "tap test/*.js"
+  },
+  "dependencies": {
+    "minimist": "^1.2.6"
+  },
+  "devDependencies": {
+    "tap": "^16.0.1"
+  },
+  "bin": "bin/cmd.js",
+  "license": "MIT",
+  "files": [
+    "bin",
+    "index.js"
+  ]
+}
diff --git a/node_modules/multer/node_modules/mkdirp/readme.markdown b/node_modules/multer/node_modules/mkdirp/readme.markdown
new file mode 100644
index 0000000000000000000000000000000000000000..fc314bfbd662cf9bb8a7290c77765b3f824d5ac8
--- /dev/null
+++ b/node_modules/multer/node_modules/mkdirp/readme.markdown
@@ -0,0 +1,100 @@
+# mkdirp
+
+Like `mkdir -p`, but in node.js!
+
+[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
+
+# example
+
+## pow.js
+
+```js
+var mkdirp = require('mkdirp');
+    
+mkdirp('/tmp/foo/bar/baz', function (err) {
+    if (err) console.error(err)
+    else console.log('pow!')
+});
+```
+
+Output
+
+```
+pow!
+```
+
+And now /tmp/foo/bar/baz exists, huzzah!
+
+# methods
+
+```js
+var mkdirp = require('mkdirp');
+```
+
+## mkdirp(dir, opts, cb)
+
+Create a new directory and any necessary subdirectories at `dir` with octal
+permission string `opts.mode`. If `opts` is a non-object, it will be treated as
+the `opts.mode`.
+
+If `opts.mode` isn't specified, it defaults to `0777`.
+
+`cb(err, made)` fires with the error or the first directory `made`
+that had to be created, if any.
+
+You can optionally pass in an alternate `fs` implementation by passing in
+`opts.fs`. Your implementation should have `opts.fs.mkdir(path, mode, cb)` and
+`opts.fs.stat(path, cb)`.
+
+## mkdirp.sync(dir, opts)
+
+Synchronously create a new directory and any necessary subdirectories at `dir`
+with octal permission string `opts.mode`. If `opts` is a non-object, it will be
+treated as the `opts.mode`.
+
+If `opts.mode` isn't specified, it defaults to `0777`.
+
+Returns the first directory that had to be created, if any.
+
+You can optionally pass in an alternate `fs` implementation by passing in
+`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)` and
+`opts.fs.statSync(path)`.
+
+# usage
+
+This package also ships with a `mkdirp` command.
+
+```
+usage: mkdirp [DIR1,DIR2..] {OPTIONS}
+
+  Create each supplied directory including any necessary parent directories that
+  don't yet exist.
+  
+  If the directory already exists, do nothing.
+
+OPTIONS are:
+
+  -m, --mode   If a directory needs to be created, set the mode as an octal
+               permission string.
+
+```
+
+# install
+
+With [npm](http://npmjs.org) do:
+
+```
+npm install mkdirp
+```
+
+to get the library, or
+
+```
+npm install -g mkdirp
+```
+
+to get the command.
+
+# license
+
+MIT
diff --git a/node_modules/multer/package.json b/node_modules/multer/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..8545a73d304da06d58bde7243faba96b8d71224e
--- /dev/null
+++ b/node_modules/multer/package.json
@@ -0,0 +1,52 @@
+{
+  "name": "multer",
+  "description": "Middleware for handling `multipart/form-data`.",
+  "version": "1.4.5-lts.1",
+  "contributors": [
+    "Hage Yaapa <captain@hacksparrow.com> (http://www.hacksparrow.com)",
+    "Jaret Pfluger <https://github.com/jpfluger>",
+    "Linus Unnebäck <linus@folkdatorn.se>"
+  ],
+  "license": "MIT",
+  "repository": "expressjs/multer",
+  "keywords": [
+    "form",
+    "post",
+    "multipart",
+    "form-data",
+    "formdata",
+    "express",
+    "middleware"
+  ],
+  "dependencies": {
+    "append-field": "^1.0.0",
+    "busboy": "^1.0.0",
+    "concat-stream": "^1.5.2",
+    "mkdirp": "^0.5.4",
+    "object-assign": "^4.1.1",
+    "type-is": "^1.6.4",
+    "xtend": "^4.0.0"
+  },
+  "devDependencies": {
+    "deep-equal": "^2.0.3",
+    "express": "^4.13.1",
+    "form-data": "^1.0.0-rc1",
+    "fs-temp": "^1.1.2",
+    "mocha": "^3.5.3",
+    "rimraf": "^2.4.1",
+    "standard": "^14.3.3",
+    "testdata-w3c-json-form": "^1.0.0"
+  },
+  "engines": {
+    "node": ">= 6.0.0"
+  },
+  "files": [
+    "LICENSE",
+    "index.js",
+    "storage/",
+    "lib/"
+  ],
+  "scripts": {
+    "test": "standard && mocha"
+  }
+}
diff --git a/node_modules/multer/storage/disk.js b/node_modules/multer/storage/disk.js
new file mode 100644
index 0000000000000000000000000000000000000000..2f77c9f133c9fd21662fd07e9ef546dae19bc53c
--- /dev/null
+++ b/node_modules/multer/storage/disk.js
@@ -0,0 +1,66 @@
+var fs = require('fs')
+var os = require('os')
+var path = require('path')
+var crypto = require('crypto')
+var mkdirp = require('mkdirp')
+
+function getFilename (req, file, cb) {
+  crypto.randomBytes(16, function (err, raw) {
+    cb(err, err ? undefined : raw.toString('hex'))
+  })
+}
+
+function getDestination (req, file, cb) {
+  cb(null, os.tmpdir())
+}
+
+function DiskStorage (opts) {
+  this.getFilename = (opts.filename || getFilename)
+
+  if (typeof opts.destination === 'string') {
+    mkdirp.sync(opts.destination)
+    this.getDestination = function ($0, $1, cb) { cb(null, opts.destination) }
+  } else {
+    this.getDestination = (opts.destination || getDestination)
+  }
+}
+
+DiskStorage.prototype._handleFile = function _handleFile (req, file, cb) {
+  var that = this
+
+  that.getDestination(req, file, function (err, destination) {
+    if (err) return cb(err)
+
+    that.getFilename(req, file, function (err, filename) {
+      if (err) return cb(err)
+
+      var finalPath = path.join(destination, filename)
+      var outStream = fs.createWriteStream(finalPath)
+
+      file.stream.pipe(outStream)
+      outStream.on('error', cb)
+      outStream.on('finish', function () {
+        cb(null, {
+          destination: destination,
+          filename: filename,
+          path: finalPath,
+          size: outStream.bytesWritten
+        })
+      })
+    })
+  })
+}
+
+DiskStorage.prototype._removeFile = function _removeFile (req, file, cb) {
+  var path = file.path
+
+  delete file.destination
+  delete file.filename
+  delete file.path
+
+  fs.unlink(path, cb)
+}
+
+module.exports = function (opts) {
+  return new DiskStorage(opts)
+}
diff --git a/node_modules/multer/storage/memory.js b/node_modules/multer/storage/memory.js
new file mode 100644
index 0000000000000000000000000000000000000000..f953ded15a2baf5cf59d3c2a716a8d5576db086c
--- /dev/null
+++ b/node_modules/multer/storage/memory.js
@@ -0,0 +1,21 @@
+var concat = require('concat-stream')
+
+function MemoryStorage (opts) {}
+
+MemoryStorage.prototype._handleFile = function _handleFile (req, file, cb) {
+  file.stream.pipe(concat({ encoding: 'buffer' }, function (data) {
+    cb(null, {
+      buffer: data,
+      size: data.length
+    })
+  }))
+}
+
+MemoryStorage.prototype._removeFile = function _removeFile (req, file, cb) {
+  delete file.buffer
+  cb(null)
+}
+
+module.exports = function (opts) {
+  return new MemoryStorage(opts)
+}
diff --git a/node_modules/streamsearch/.eslintrc.js b/node_modules/streamsearch/.eslintrc.js
new file mode 100644
index 0000000000000000000000000000000000000000..be9311d02655a22381f13078bfe868bcbd85b3a6
--- /dev/null
+++ b/node_modules/streamsearch/.eslintrc.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = {
+  extends: '@mscdex/eslint-config',
+};
diff --git a/node_modules/streamsearch/.github/workflows/ci.yml b/node_modules/streamsearch/.github/workflows/ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..29d51782c77a93f2a32774350fb6e6229ebc3408
--- /dev/null
+++ b/node_modules/streamsearch/.github/workflows/ci.yml
@@ -0,0 +1,24 @@
+name: CI
+
+on:
+  pull_request:
+  push:
+    branches: [ master ]
+
+jobs:
+  tests-linux:
+    runs-on: ubuntu-latest
+    strategy:
+      fail-fast: false
+      matrix:
+        node-version: [10.x, 12.x, 14.x, 16.x]
+    steps:
+      - uses: actions/checkout@v2
+      - name: Use Node.js ${{ matrix.node-version }}
+        uses: actions/setup-node@v1
+        with:
+          node-version: ${{ matrix.node-version }}
+      - name: Install module
+        run: npm install
+      - name: Run tests
+        run: npm test
diff --git a/node_modules/streamsearch/.github/workflows/lint.yml b/node_modules/streamsearch/.github/workflows/lint.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9f9e1f589a30be583a860f928382b3033c38749d
--- /dev/null
+++ b/node_modules/streamsearch/.github/workflows/lint.yml
@@ -0,0 +1,23 @@
+name: lint
+
+on:
+  pull_request:
+  push:
+    branches: [ master ]
+
+env:
+  NODE_VERSION: 16.x
+
+jobs:
+  lint-js:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      - name: Use Node.js ${{ env.NODE_VERSION }}
+        uses: actions/setup-node@v1
+        with:
+          node-version: ${{ env.NODE_VERSION }}
+      - name: Install ESLint + ESLint configs/plugins
+        run: npm install --only=dev
+      - name: Lint files
+        run: npm run lint
diff --git a/node_modules/streamsearch/LICENSE b/node_modules/streamsearch/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..290762e94f4e2f2b52cc13ae4f2b63ac0269bfd1
--- /dev/null
+++ b/node_modules/streamsearch/LICENSE
@@ -0,0 +1,19 @@
+Copyright Brian White. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
\ No newline at end of file
diff --git a/node_modules/streamsearch/README.md b/node_modules/streamsearch/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c3934d1c7d57119aa31103bc6389838c646e2fc2
--- /dev/null
+++ b/node_modules/streamsearch/README.md
@@ -0,0 +1,95 @@
+Description
+===========
+
+streamsearch is a module for [node.js](http://nodejs.org/) that allows searching a stream using the Boyer-Moore-Horspool algorithm.
+
+This module is based heavily on the Streaming Boyer-Moore-Horspool C++ implementation by Hongli Lai [here](https://github.com/FooBarWidget/boyer-moore-horspool).
+
+
+Requirements
+============
+
+* [node.js](http://nodejs.org/) -- v10.0.0 or newer
+
+
+Installation
+============
+
+    npm install streamsearch
+
+Example
+=======
+
+```js
+  const { inspect } = require('util');
+
+  const StreamSearch = require('streamsearch');
+
+  const needle = Buffer.from('\r\n');
+  const ss = new StreamSearch(needle, (isMatch, data, start, end) => {
+    if (data)
+      console.log('data: ' + inspect(data.toString('latin1', start, end)));
+    if (isMatch)
+      console.log('match!');
+  });
+
+  const chunks = [
+    'foo',
+    ' bar',
+    '\r',
+    '\n',
+    'baz, hello\r',
+    '\n world.',
+    '\r\n Node.JS rules!!\r\n\r\n',
+  ];
+  for (const chunk of chunks)
+    ss.push(Buffer.from(chunk));
+
+  // output:
+  //
+  // data: 'foo'
+  // data: ' bar'
+  // match!
+  // data: 'baz, hello'
+  // match!
+  // data: ' world.'
+  // match!
+  // data: ' Node.JS rules!!'
+  // match!
+  // data: ''
+  // match!
+```
+
+
+API
+===
+
+Properties
+----------
+
+* **maxMatches** - < _integer_ > - The maximum number of matches. Defaults to `Infinity`.
+
+* **matches** - < _integer_ > - The current match count.
+
+
+Functions
+---------
+
+* **(constructor)**(< _mixed_ >needle, < _function_ >callback) - Creates and returns a new instance for searching for a _Buffer_ or _string_ `needle`. `callback` is called any time there is non-matching data and/or there is a needle match. `callback` will be called with the following arguments:
+
+  1. `isMatch` - _boolean_ - Indicates whether a match has been found
+
+  2. `data` - _mixed_ - If set, this contains data that did not match the needle.
+
+  3. `start` - _integer_ - The index in `data` where the non-matching data begins (inclusive).
+
+  4. `end` - _integer_ - The index in `data` where the non-matching data ends (exclusive).
+
+  5. `isSafeData` - _boolean_ - Indicates if it is safe to store a reference to `data` (e.g. as-is or via `data.slice()`) or not, as in some cases `data` may point to a Buffer whose contents change over time.
+
+* **destroy**() - _(void)_ - Emits any last remaining unmatched data that may still be buffered and then resets internal state.
+
+* **push**(< _Buffer_ >chunk) - _integer_ - Processes `chunk`, searching for a match. The return value is the last processed index in `chunk` + 1.
+
+* **reset**() - _(void)_ - Resets internal state. Useful for when you wish to start searching a new/different stream for example.
+
diff --git a/node_modules/streamsearch/lib/sbmh.js b/node_modules/streamsearch/lib/sbmh.js
new file mode 100644
index 0000000000000000000000000000000000000000..510cae26e67a58d4c1cdfb4ed5afd80c0f50c782
--- /dev/null
+++ b/node_modules/streamsearch/lib/sbmh.js
@@ -0,0 +1,267 @@
+'use strict';
+/*
+  Based heavily on the Streaming Boyer-Moore-Horspool C++ implementation
+  by Hongli Lai at: https://github.com/FooBarWidget/boyer-moore-horspool
+*/
+function memcmp(buf1, pos1, buf2, pos2, num) {
+  for (let i = 0; i < num; ++i) {
+    if (buf1[pos1 + i] !== buf2[pos2 + i])
+      return false;
+  }
+  return true;
+}
+
+class SBMH {
+  constructor(needle, cb) {
+    if (typeof cb !== 'function')
+      throw new Error('Missing match callback');
+
+    if (typeof needle === 'string')
+      needle = Buffer.from(needle);
+    else if (!Buffer.isBuffer(needle))
+      throw new Error(`Expected Buffer for needle, got ${typeof needle}`);
+
+    const needleLen = needle.length;
+
+    this.maxMatches = Infinity;
+    this.matches = 0;
+
+    this._cb = cb;
+    this._lookbehindSize = 0;
+    this._needle = needle;
+    this._bufPos = 0;
+
+    this._lookbehind = Buffer.allocUnsafe(needleLen);
+
+    // Initialize occurrence table.
+    this._occ = [
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen, needleLen, needleLen,
+      needleLen, needleLen, needleLen, needleLen
+    ];
+
+    // Populate occurrence table with analysis of the needle, ignoring the last
+    // letter.
+    if (needleLen > 1) {
+      for (let i = 0; i < needleLen - 1; ++i)
+        this._occ[needle[i]] = needleLen - 1 - i;
+    }
+  }
+
+  reset() {
+    this.matches = 0;
+    this._lookbehindSize = 0;
+    this._bufPos = 0;
+  }
+
+  push(chunk, pos) {
+    let result;
+    if (!Buffer.isBuffer(chunk))
+      chunk = Buffer.from(chunk, 'latin1');
+    const chunkLen = chunk.length;
+    this._bufPos = pos || 0;
+    while (result !== chunkLen && this.matches < this.maxMatches)
+      result = feed(this, chunk);
+    return result;
+  }
+
+  destroy() {
+    const lbSize = this._lookbehindSize;
+    if (lbSize)
+      this._cb(false, this._lookbehind, 0, lbSize, false);
+    this.reset();
+  }
+}
+
+function feed(self, data) {
+  const len = data.length;
+  const needle = self._needle;
+  const needleLen = needle.length;
+
+  // Positive: points to a position in `data`
+  //           pos == 3 points to data[3]
+  // Negative: points to a position in the lookbehind buffer
+  //           pos == -2 points to lookbehind[lookbehindSize - 2]
+  let pos = -self._lookbehindSize;
+  const lastNeedleCharPos = needleLen - 1;
+  const lastNeedleChar = needle[lastNeedleCharPos];
+  const end = len - needleLen;
+  const occ = self._occ;
+  const lookbehind = self._lookbehind;
+
+  if (pos < 0) {
+    // Lookbehind buffer is not empty. Perform Boyer-Moore-Horspool
+    // search with character lookup code that considers both the
+    // lookbehind buffer and the current round's haystack data.
+    //
+    // Loop until
+    //   there is a match.
+    // or until
+    //   we've moved past the position that requires the
+    //   lookbehind buffer. In this case we switch to the
+    //   optimized loop.
+    // or until
+    //   the character to look at lies outside the haystack.
+    while (pos < 0 && pos <= end) {
+      const nextPos = pos + lastNeedleCharPos;
+      const ch = (nextPos < 0
+                  ? lookbehind[self._lookbehindSize + nextPos]
+                  : data[nextPos]);
+
+      if (ch === lastNeedleChar
+          && matchNeedle(self, data, pos, lastNeedleCharPos)) {
+        self._lookbehindSize = 0;
+        ++self.matches;
+        if (pos > -self._lookbehindSize)
+          self._cb(true, lookbehind, 0, self._lookbehindSize + pos, false);
+        else
+          self._cb(true, undefined, 0, 0, true);
+
+        return (self._bufPos = pos + needleLen);
+      }
+
+      pos += occ[ch];
+    }
+
+    // No match.
+
+    // There's too few data for Boyer-Moore-Horspool to run,
+    // so let's use a different algorithm to skip as much as
+    // we can.
+    // Forward pos until
+    //   the trailing part of lookbehind + data
+    //   looks like the beginning of the needle
+    // or until
+    //   pos == 0
+    while (pos < 0 && !matchNeedle(self, data, pos, len - pos))
+      ++pos;
+
+    if (pos < 0) {
+      // Cut off part of the lookbehind buffer that has
+      // been processed and append the entire haystack
+      // into it.
+      const bytesToCutOff = self._lookbehindSize + pos;
+
+      if (bytesToCutOff > 0) {
+        // The cut off data is guaranteed not to contain the needle.
+        self._cb(false, lookbehind, 0, bytesToCutOff, false);
+      }
+
+      self._lookbehindSize -= bytesToCutOff;
+      lookbehind.copy(lookbehind, 0, bytesToCutOff, self._lookbehindSize);
+      lookbehind.set(data, self._lookbehindSize);
+      self._lookbehindSize += len;
+
+      self._bufPos = len;
+      return len;
+    }
+
+    // Discard lookbehind buffer.
+    self._cb(false, lookbehind, 0, self._lookbehindSize, false);
+    self._lookbehindSize = 0;
+  }
+
+  pos += self._bufPos;
+
+  const firstNeedleChar = needle[0];
+
+  // Lookbehind buffer is now empty. Perform Boyer-Moore-Horspool
+  // search with optimized character lookup code that only considers
+  // the current round's haystack data.
+  while (pos <= end) {
+    const ch = data[pos + lastNeedleCharPos];
+
+    if (ch === lastNeedleChar
+        && data[pos] === firstNeedleChar
+        && memcmp(needle, 0, data, pos, lastNeedleCharPos)) {
+      ++self.matches;
+      if (pos > 0)
+        self._cb(true, data, self._bufPos, pos, true);
+      else
+        self._cb(true, undefined, 0, 0, true);
+
+      return (self._bufPos = pos + needleLen);
+    }
+
+    pos += occ[ch];
+  }
+
+  // There was no match. If there's trailing haystack data that we cannot
+  // match yet using the Boyer-Moore-Horspool algorithm (because the trailing
+  // data is less than the needle size) then match using a modified
+  // algorithm that starts matching from the beginning instead of the end.
+  // Whatever trailing data is left after running this algorithm is added to
+  // the lookbehind buffer.
+  while (pos < len) {
+    if (data[pos] !== firstNeedleChar
+        || !memcmp(data, pos, needle, 0, len - pos)) {
+      ++pos;
+      continue;
+    }
+    data.copy(lookbehind, 0, pos, len);
+    self._lookbehindSize = len - pos;
+    break;
+  }
+
+  // Everything until `pos` is guaranteed not to contain needle data.
+  if (pos > 0)
+    self._cb(false, data, self._bufPos, pos < len ? pos : len, true);
+
+  self._bufPos = len;
+  return len;
+}
+
+function matchNeedle(self, data, pos, len) {
+  const lb = self._lookbehind;
+  const lbSize = self._lookbehindSize;
+  const needle = self._needle;
+
+  for (let i = 0; i < len; ++i, ++pos) {
+    const ch = (pos < 0 ? lb[lbSize + pos] : data[pos]);
+    if (ch !== needle[i])
+      return false;
+  }
+  return true;
+}
+
+module.exports = SBMH;
diff --git a/node_modules/streamsearch/package.json b/node_modules/streamsearch/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..51df8f9707cebd8469d793a8d90050baac1c4d1d
--- /dev/null
+++ b/node_modules/streamsearch/package.json
@@ -0,0 +1,34 @@
+{
+  "name": "streamsearch",
+  "version": "1.1.0",
+  "author": "Brian White <mscdex@mscdex.net>",
+  "description": "Streaming Boyer-Moore-Horspool searching for node.js",
+  "main": "./lib/sbmh.js",
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "devDependencies": {
+    "@mscdex/eslint-config": "^1.1.0",
+    "eslint": "^7.32.0"
+  },
+  "scripts": {
+    "test": "node test/test.js",
+    "lint": "eslint --cache --report-unused-disable-directives --ext=.js .eslintrc.js lib test",
+    "lint:fix": "npm run lint -- --fix"
+  },
+  "keywords": [
+    "stream",
+    "horspool",
+    "boyer-moore-horspool",
+    "boyer-moore",
+    "search"
+  ],
+  "licenses": [{
+    "type": "MIT",
+    "url": "http://github.com/mscdex/streamsearch/raw/master/LICENSE"
+  }],
+  "repository": {
+    "type": "git",
+    "url": "http://github.com/mscdex/streamsearch.git"
+  }
+}
diff --git a/node_modules/streamsearch/test/test.js b/node_modules/streamsearch/test/test.js
new file mode 100644
index 0000000000000000000000000000000000000000..39a04d7f834bea5e8da37c4cf56973a7b3217dd5
--- /dev/null
+++ b/node_modules/streamsearch/test/test.js
@@ -0,0 +1,70 @@
+'use strict';
+
+const assert = require('assert');
+
+const StreamSearch = require('../lib/sbmh.js');
+
+[
+  {
+    needle: '\r\n',
+    chunks: [
+      'foo',
+      ' bar',
+      '\r',
+      '\n',
+      'baz, hello\r',
+      '\n world.',
+      '\r\n Node.JS rules!!\r\n\r\n',
+    ],
+    expect: [
+      [false, 'foo'],
+      [false, ' bar'],
+      [ true, null],
+      [false, 'baz, hello'],
+      [ true, null],
+      [false, ' world.'],
+      [ true, null],
+      [ true, ' Node.JS rules!!'],
+      [ true, ''],
+    ],
+  },
+  {
+    needle: '---foobarbaz',
+    chunks: [
+      '---foobarbaz',
+      'asdf',
+      '\r\n',
+      '---foobarba',
+      '---foobar',
+      'ba',
+      '\r\n---foobarbaz--\r\n',
+    ],
+    expect: [
+      [ true, null],
+      [false, 'asdf'],
+      [false, '\r\n'],
+      [false, '---foobarba'],
+      [false, '---foobarba'],
+      [ true, '\r\n'],
+      [false, '--\r\n'],
+    ],
+  },
+].forEach((test, i) => {
+  console.log(`Running test #${i + 1}`);
+  const { needle, chunks, expect } = test;
+
+  const results = [];
+  const ss = new StreamSearch(Buffer.from(needle),
+                              (isMatch, data, start, end) => {
+    if (data)
+      data = data.toString('latin1', start, end);
+    else
+      data = null;
+    results.push([isMatch, data]);
+  });
+
+  for (const chunk of chunks)
+    ss.push(Buffer.from(chunk));
+
+  assert.deepStrictEqual(results, expect);
+});
diff --git a/node_modules/supports-color/index.js b/node_modules/supports-color/index.js
index 1704131bdf6c8f1bddd360ed0ce42185590d2787..6fada390fb88d8e1dae3454216aa3995141a1785 100644
--- a/node_modules/supports-color/index.js
+++ b/node_modules/supports-color/index.js
@@ -1,22 +1,31 @@
 'use strict';
 const os = require('os');
+const tty = require('tty');
 const hasFlag = require('has-flag');
 
-const env = process.env;
+const {env} = process;
 
 let forceColor;
 if (hasFlag('no-color') ||
 	hasFlag('no-colors') ||
-	hasFlag('color=false')) {
-	forceColor = false;
+	hasFlag('color=false') ||
+	hasFlag('color=never')) {
+	forceColor = 0;
 } else if (hasFlag('color') ||
 	hasFlag('colors') ||
 	hasFlag('color=true') ||
 	hasFlag('color=always')) {
-	forceColor = true;
+	forceColor = 1;
 }
+
 if ('FORCE_COLOR' in env) {
-	forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0;
+	if (env.FORCE_COLOR === 'true') {
+		forceColor = 1;
+	} else if (env.FORCE_COLOR === 'false') {
+		forceColor = 0;
+	} else {
+		forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
+	}
 }
 
 function translateLevel(level) {
@@ -32,8 +41,8 @@ function translateLevel(level) {
 	};
 }
 
-function supportsColor(stream) {
-	if (forceColor === false) {
+function supportsColor(haveStream, streamIsTTY) {
+	if (forceColor === 0) {
 		return 0;
 	}
 
@@ -47,22 +56,21 @@ function supportsColor(stream) {
 		return 2;
 	}
 
-	if (stream && !stream.isTTY && forceColor !== true) {
+	if (haveStream && !streamIsTTY && forceColor === undefined) {
 		return 0;
 	}
 
-	const min = forceColor ? 1 : 0;
+	const min = forceColor || 0;
+
+	if (env.TERM === 'dumb') {
+		return min;
+	}
 
 	if (process.platform === 'win32') {
-		// Node.js 7.5.0 is the first version of Node.js to include a patch to
-		// libuv that enables 256 color output on Windows. Anything earlier and it
-		// won't work. However, here we target Node.js 8 at minimum as it is an LTS
-		// release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows
-		// release that supports 256 colors. Windows 10 build 14931 is the first release
-		// that supports 16m/TrueColor.
+		// Windows 10 build 10586 is the first Windows release that supports 256 colors.
+		// Windows 10 build 14931 is the first release that supports 16m/TrueColor.
 		const osRelease = os.release().split('.');
 		if (
-			Number(process.versions.node.split('.')[0]) >= 8 &&
 			Number(osRelease[0]) >= 10 &&
 			Number(osRelease[2]) >= 10586
 		) {
@@ -73,7 +81,7 @@ function supportsColor(stream) {
 	}
 
 	if ('CI' in env) {
-		if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
+		if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
 			return 1;
 		}
 
@@ -112,20 +120,16 @@ function supportsColor(stream) {
 		return 1;
 	}
 
-	if (env.TERM === 'dumb') {
-		return min;
-	}
-
 	return min;
 }
 
 function getSupportLevel(stream) {
-	const level = supportsColor(stream);
+	const level = supportsColor(stream, stream && stream.isTTY);
 	return translateLevel(level);
 }
 
 module.exports = {
 	supportsColor: getSupportLevel,
-	stdout: getSupportLevel(process.stdout),
-	stderr: getSupportLevel(process.stderr)
+	stdout: translateLevel(supportsColor(true, tty.isatty(1))),
+	stderr: translateLevel(supportsColor(true, tty.isatty(2)))
 };
diff --git a/node_modules/supports-color/package.json b/node_modules/supports-color/package.json
index ad199f5cdb0436335d11d8650821e394bd276e56..f7182edcea2baa8778219d4aab2c0c1b21f1a30a 100644
--- a/node_modules/supports-color/package.json
+++ b/node_modules/supports-color/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "supports-color",
-	"version": "5.5.0",
+	"version": "7.2.0",
 	"description": "Detect whether a terminal supports color",
 	"license": "MIT",
 	"repository": "chalk/supports-color",
@@ -10,7 +10,7 @@
 		"url": "sindresorhus.com"
 	},
 	"engines": {
-		"node": ">=4"
+		"node": ">=8"
 	},
 	"scripts": {
 		"test": "xo && ava"
@@ -42,12 +42,12 @@
 		"16m"
 	],
 	"dependencies": {
-		"has-flag": "^3.0.0"
+		"has-flag": "^4.0.0"
 	},
 	"devDependencies": {
-		"ava": "^0.25.0",
-		"import-fresh": "^2.0.0",
-		"xo": "^0.20.0"
+		"ava": "^1.4.1",
+		"import-fresh": "^3.0.0",
+		"xo": "^0.24.0"
 	},
 	"browser": "browser.js"
 }
diff --git a/node_modules/supports-color/readme.md b/node_modules/supports-color/readme.md
index f6e40195730ae8c665bdd898cfe0442e9ac08105..36542285863330887923979b4c00579738907d49 100644
--- a/node_modules/supports-color/readme.md
+++ b/node_modules/supports-color/readme.md
@@ -44,7 +44,7 @@ The `stdout`/`stderr` objects specifies a level of support for color through a `
 
 It obeys the `--color` and `--no-color` CLI flags.
 
-Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add the environment variable `FORCE_COLOR=1` to forcefully enable color or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
+For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
 
 Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
 
@@ -61,6 +61,16 @@ Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=
 - [Josh Junon](https://github.com/qix-)
 
 
-## License
+---
 
-MIT
+<div align="center">
+	<b>
+		<a href="https://tidelift.com/subscription/pkg/npm-supports-color?utm_source=npm-supports-color&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
+	</b>
+	<br>
+	<sub>
+		Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
+	</sub>
+</div>
+
+---
diff --git a/node_modules/async/.travis.yml b/node_modules/typedarray/.travis.yml
similarity index 63%
rename from node_modules/async/.travis.yml
rename to node_modules/typedarray/.travis.yml
index 6064ca09264adc3d4418307d664a17353d8a2cc0..cc4dba29d959a2da7b97f9edd3c7c91384b2ee5b 100644
--- a/node_modules/async/.travis.yml
+++ b/node_modules/typedarray/.travis.yml
@@ -1,5 +1,4 @@
 language: node_js
 node_js:
+  - "0.8"
   - "0.10"
-  - "0.12"
-  - "iojs"
diff --git a/node_modules/typedarray/LICENSE b/node_modules/typedarray/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..11adfaec9e7f95f3eab1ecdd6f1f8715fcdc4311
--- /dev/null
+++ b/node_modules/typedarray/LICENSE
@@ -0,0 +1,35 @@
+/*
+ Copyright (c) 2010, Linden Research, Inc.
+ Copyright (c) 2012, Joshua Bell
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ $/LicenseInfo$
+ */
+
+// Original can be found at:
+//   https://bitbucket.org/lindenlab/llsd
+// Modifications by Joshua Bell inexorabletash@gmail.com
+//   https://github.com/inexorabletash/polyfill
+
+// ES3/ES5 implementation of the Krhonos Typed Array Specification
+//   Ref: http://www.khronos.org/registry/typedarray/specs/latest/
+//   Date: 2011-02-01
+//
+// Variations:
+//  * Allows typed_array.get/set() as alias for subscripts (typed_array[])
diff --git a/node_modules/typedarray/example/tarray.js b/node_modules/typedarray/example/tarray.js
new file mode 100644
index 0000000000000000000000000000000000000000..8423d7c9b1c327e5c76744eccf7ec469b3ffdd79
--- /dev/null
+++ b/node_modules/typedarray/example/tarray.js
@@ -0,0 +1,4 @@
+var Uint8Array = require('../').Uint8Array;
+var ua = new Uint8Array(5);
+ua[1] = 256 + 55;
+console.log(ua[1]);
diff --git a/node_modules/typedarray/index.js b/node_modules/typedarray/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..5e540841f432413f874b4c75ffc7280f114c37eb
--- /dev/null
+++ b/node_modules/typedarray/index.js
@@ -0,0 +1,630 @@
+var undefined = (void 0); // Paranoia
+
+// Beyond this value, index getters/setters (i.e. array[0], array[1]) are so slow to
+// create, and consume so much memory, that the browser appears frozen.
+var MAX_ARRAY_LENGTH = 1e5;
+
+// Approximations of internal ECMAScript conversion functions
+var ECMAScript = (function() {
+  // Stash a copy in case other scripts modify these
+  var opts = Object.prototype.toString,
+      ophop = Object.prototype.hasOwnProperty;
+
+  return {
+    // Class returns internal [[Class]] property, used to avoid cross-frame instanceof issues:
+    Class: function(v) { return opts.call(v).replace(/^\[object *|\]$/g, ''); },
+    HasProperty: function(o, p) { return p in o; },
+    HasOwnProperty: function(o, p) { return ophop.call(o, p); },
+    IsCallable: function(o) { return typeof o === 'function'; },
+    ToInt32: function(v) { return v >> 0; },
+    ToUint32: function(v) { return v >>> 0; }
+  };
+}());
+
+// Snapshot intrinsics
+var LN2 = Math.LN2,
+    abs = Math.abs,
+    floor = Math.floor,
+    log = Math.log,
+    min = Math.min,
+    pow = Math.pow,
+    round = Math.round;
+
+// ES5: lock down object properties
+function configureProperties(obj) {
+  if (getOwnPropNames && defineProp) {
+    var props = getOwnPropNames(obj), i;
+    for (i = 0; i < props.length; i += 1) {
+      defineProp(obj, props[i], {
+        value: obj[props[i]],
+        writable: false,
+        enumerable: false,
+        configurable: false
+      });
+    }
+  }
+}
+
+// emulate ES5 getter/setter API using legacy APIs
+// http://blogs.msdn.com/b/ie/archive/2010/09/07/transitioning-existing-code-to-the-es5-getter-setter-apis.aspx
+// (second clause tests for Object.defineProperty() in IE<9 that only supports extending DOM prototypes, but
+// note that IE<9 does not support __defineGetter__ or __defineSetter__ so it just renders the method harmless)
+var defineProp
+if (Object.defineProperty && (function() {
+      try {
+        Object.defineProperty({}, 'x', {});
+        return true;
+      } catch (e) {
+        return false;
+      }
+    })()) {
+  defineProp = Object.defineProperty;
+} else {
+  defineProp = function(o, p, desc) {
+    if (!o === Object(o)) throw new TypeError("Object.defineProperty called on non-object");
+    if (ECMAScript.HasProperty(desc, 'get') && Object.prototype.__defineGetter__) { Object.prototype.__defineGetter__.call(o, p, desc.get); }
+    if (ECMAScript.HasProperty(desc, 'set') && Object.prototype.__defineSetter__) { Object.prototype.__defineSetter__.call(o, p, desc.set); }
+    if (ECMAScript.HasProperty(desc, 'value')) { o[p] = desc.value; }
+    return o;
+  };
+}
+
+var getOwnPropNames = Object.getOwnPropertyNames || function (o) {
+  if (o !== Object(o)) throw new TypeError("Object.getOwnPropertyNames called on non-object");
+  var props = [], p;
+  for (p in o) {
+    if (ECMAScript.HasOwnProperty(o, p)) {
+      props.push(p);
+    }
+  }
+  return props;
+};
+
+// ES5: Make obj[index] an alias for obj._getter(index)/obj._setter(index, value)
+// for index in 0 ... obj.length
+function makeArrayAccessors(obj) {
+  if (!defineProp) { return; }
+
+  if (obj.length > MAX_ARRAY_LENGTH) throw new RangeError("Array too large for polyfill");
+
+  function makeArrayAccessor(index) {
+    defineProp(obj, index, {
+      'get': function() { return obj._getter(index); },
+      'set': function(v) { obj._setter(index, v); },
+      enumerable: true,
+      configurable: false
+    });
+  }
+
+  var i;
+  for (i = 0; i < obj.length; i += 1) {
+    makeArrayAccessor(i);
+  }
+}
+
+// Internal conversion functions:
+//    pack<Type>()   - take a number (interpreted as Type), output a byte array
+//    unpack<Type>() - take a byte array, output a Type-like number
+
+function as_signed(value, bits) { var s = 32 - bits; return (value << s) >> s; }
+function as_unsigned(value, bits) { var s = 32 - bits; return (value << s) >>> s; }
+
+function packI8(n) { return [n & 0xff]; }
+function unpackI8(bytes) { return as_signed(bytes[0], 8); }
+
+function packU8(n) { return [n & 0xff]; }
+function unpackU8(bytes) { return as_unsigned(bytes[0], 8); }
+
+function packU8Clamped(n) { n = round(Number(n)); return [n < 0 ? 0 : n > 0xff ? 0xff : n & 0xff]; }
+
+function packI16(n) { return [(n >> 8) & 0xff, n & 0xff]; }
+function unpackI16(bytes) { return as_signed(bytes[0] << 8 | bytes[1], 16); }
+
+function packU16(n) { return [(n >> 8) & 0xff, n & 0xff]; }
+function unpackU16(bytes) { return as_unsigned(bytes[0] << 8 | bytes[1], 16); }
+
+function packI32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; }
+function unpackI32(bytes) { return as_signed(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); }
+
+function packU32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; }
+function unpackU32(bytes) { return as_unsigned(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); }
+
+function packIEEE754(v, ebits, fbits) {
+
+  var bias = (1 << (ebits - 1)) - 1,
+      s, e, f, ln,
+      i, bits, str, bytes;
+
+  function roundToEven(n) {
+    var w = floor(n), f = n - w;
+    if (f < 0.5)
+      return w;
+    if (f > 0.5)
+      return w + 1;
+    return w % 2 ? w + 1 : w;
+  }
+
+  // Compute sign, exponent, fraction
+  if (v !== v) {
+    // NaN
+    // http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping
+    e = (1 << ebits) - 1; f = pow(2, fbits - 1); s = 0;
+  } else if (v === Infinity || v === -Infinity) {
+    e = (1 << ebits) - 1; f = 0; s = (v < 0) ? 1 : 0;
+  } else if (v === 0) {
+    e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0;
+  } else {
+    s = v < 0;
+    v = abs(v);
+
+    if (v >= pow(2, 1 - bias)) {
+      e = min(floor(log(v) / LN2), 1023);
+      f = roundToEven(v / pow(2, e) * pow(2, fbits));
+      if (f / pow(2, fbits) >= 2) {
+        e = e + 1;
+        f = 1;
+      }
+      if (e > bias) {
+        // Overflow
+        e = (1 << ebits) - 1;
+        f = 0;
+      } else {
+        // Normalized
+        e = e + bias;
+        f = f - pow(2, fbits);
+      }
+    } else {
+      // Denormalized
+      e = 0;
+      f = roundToEven(v / pow(2, 1 - bias - fbits));
+    }
+  }
+
+  // Pack sign, exponent, fraction
+  bits = [];
+  for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = floor(f / 2); }
+  for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = floor(e / 2); }
+  bits.push(s ? 1 : 0);
+  bits.reverse();
+  str = bits.join('');
+
+  // Bits to bytes
+  bytes = [];
+  while (str.length) {
+    bytes.push(parseInt(str.substring(0, 8), 2));
+    str = str.substring(8);
+  }
+  return bytes;
+}
+
+function unpackIEEE754(bytes, ebits, fbits) {
+
+  // Bytes to bits
+  var bits = [], i, j, b, str,
+      bias, s, e, f;
+
+  for (i = bytes.length; i; i -= 1) {
+    b = bytes[i - 1];
+    for (j = 8; j; j -= 1) {
+      bits.push(b % 2 ? 1 : 0); b = b >> 1;
+    }
+  }
+  bits.reverse();
+  str = bits.join('');
+
+  // Unpack sign, exponent, fraction
+  bias = (1 << (ebits - 1)) - 1;
+  s = parseInt(str.substring(0, 1), 2) ? -1 : 1;
+  e = parseInt(str.substring(1, 1 + ebits), 2);
+  f = parseInt(str.substring(1 + ebits), 2);
+
+  // Produce number
+  if (e === (1 << ebits) - 1) {
+    return f !== 0 ? NaN : s * Infinity;
+  } else if (e > 0) {
+    // Normalized
+    return s * pow(2, e - bias) * (1 + f / pow(2, fbits));
+  } else if (f !== 0) {
+    // Denormalized
+    return s * pow(2, -(bias - 1)) * (f / pow(2, fbits));
+  } else {
+    return s < 0 ? -0 : 0;
+  }
+}
+
+function unpackF64(b) { return unpackIEEE754(b, 11, 52); }
+function packF64(v) { return packIEEE754(v, 11, 52); }
+function unpackF32(b) { return unpackIEEE754(b, 8, 23); }
+function packF32(v) { return packIEEE754(v, 8, 23); }
+
+
+//
+// 3 The ArrayBuffer Type
+//
+
+(function() {
+
+  /** @constructor */
+  var ArrayBuffer = function ArrayBuffer(length) {
+    length = ECMAScript.ToInt32(length);
+    if (length < 0) throw new RangeError('ArrayBuffer size is not a small enough positive integer');
+
+    this.byteLength = length;
+    this._bytes = [];
+    this._bytes.length = length;
+
+    var i;
+    for (i = 0; i < this.byteLength; i += 1) {
+      this._bytes[i] = 0;
+    }
+
+    configureProperties(this);
+  };
+
+  exports.ArrayBuffer = exports.ArrayBuffer || ArrayBuffer;
+
+  //
+  // 4 The ArrayBufferView Type
+  //
+
+  // NOTE: this constructor is not exported
+  /** @constructor */
+  var ArrayBufferView = function ArrayBufferView() {
+    //this.buffer = null;
+    //this.byteOffset = 0;
+    //this.byteLength = 0;
+  };
+
+  //
+  // 5 The Typed Array View Types
+  //
+
+  function makeConstructor(bytesPerElement, pack, unpack) {
+    // Each TypedArray type requires a distinct constructor instance with
+    // identical logic, which this produces.
+
+    var ctor;
+    ctor = function(buffer, byteOffset, length) {
+      var array, sequence, i, s;
+
+      if (!arguments.length || typeof arguments[0] === 'number') {
+        // Constructor(unsigned long length)
+        this.length = ECMAScript.ToInt32(arguments[0]);
+        if (length < 0) throw new RangeError('ArrayBufferView size is not a small enough positive integer');
+
+        this.byteLength = this.length * this.BYTES_PER_ELEMENT;
+        this.buffer = new ArrayBuffer(this.byteLength);
+        this.byteOffset = 0;
+      } else if (typeof arguments[0] === 'object' && arguments[0].constructor === ctor) {
+        // Constructor(TypedArray array)
+        array = arguments[0];
+
+        this.length = array.length;
+        this.byteLength = this.length * this.BYTES_PER_ELEMENT;
+        this.buffer = new ArrayBuffer(this.byteLength);
+        this.byteOffset = 0;
+
+        for (i = 0; i < this.length; i += 1) {
+          this._setter(i, array._getter(i));
+        }
+      } else if (typeof arguments[0] === 'object' &&
+                 !(arguments[0] instanceof ArrayBuffer || ECMAScript.Class(arguments[0]) === 'ArrayBuffer')) {
+        // Constructor(sequence<type> array)
+        sequence = arguments[0];
+
+        this.length = ECMAScript.ToUint32(sequence.length);
+        this.byteLength = this.length * this.BYTES_PER_ELEMENT;
+        this.buffer = new ArrayBuffer(this.byteLength);
+        this.byteOffset = 0;
+
+        for (i = 0; i < this.length; i += 1) {
+          s = sequence[i];
+          this._setter(i, Number(s));
+        }
+      } else if (typeof arguments[0] === 'object' &&
+                 (arguments[0] instanceof ArrayBuffer || ECMAScript.Class(arguments[0]) === 'ArrayBuffer')) {
+        // Constructor(ArrayBuffer buffer,
+        //             optional unsigned long byteOffset, optional unsigned long length)
+        this.buffer = buffer;
+
+        this.byteOffset = ECMAScript.ToUint32(byteOffset);
+        if (this.byteOffset > this.buffer.byteLength) {
+          throw new RangeError("byteOffset out of range");
+        }
+
+        if (this.byteOffset % this.BYTES_PER_ELEMENT) {
+          // The given byteOffset must be a multiple of the element
+          // size of the specific type, otherwise an exception is raised.
+          throw new RangeError("ArrayBuffer length minus the byteOffset is not a multiple of the element size.");
+        }
+
+        if (arguments.length < 3) {
+          this.byteLength = this.buffer.byteLength - this.byteOffset;
+
+          if (this.byteLength % this.BYTES_PER_ELEMENT) {
+            throw new RangeError("length of buffer minus byteOffset not a multiple of the element size");
+          }
+          this.length = this.byteLength / this.BYTES_PER_ELEMENT;
+        } else {
+          this.length = ECMAScript.ToUint32(length);
+          this.byteLength = this.length * this.BYTES_PER_ELEMENT;
+        }
+
+        if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) {
+          throw new RangeError("byteOffset and length reference an area beyond the end of the buffer");
+        }
+      } else {
+        throw new TypeError("Unexpected argument type(s)");
+      }
+
+      this.constructor = ctor;
+
+      configureProperties(this);
+      makeArrayAccessors(this);
+    };
+
+    ctor.prototype = new ArrayBufferView();
+    ctor.prototype.BYTES_PER_ELEMENT = bytesPerElement;
+    ctor.prototype._pack = pack;
+    ctor.prototype._unpack = unpack;
+    ctor.BYTES_PER_ELEMENT = bytesPerElement;
+
+    // getter type (unsigned long index);
+    ctor.prototype._getter = function(index) {
+      if (arguments.length < 1) throw new SyntaxError("Not enough arguments");
+
+      index = ECMAScript.ToUint32(index);
+      if (index >= this.length) {
+        return undefined;
+      }
+
+      var bytes = [], i, o;
+      for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT;
+           i < this.BYTES_PER_ELEMENT;
+           i += 1, o += 1) {
+        bytes.push(this.buffer._bytes[o]);
+      }
+      return this._unpack(bytes);
+    };
+
+    // NONSTANDARD: convenience alias for getter: type get(unsigned long index);
+    ctor.prototype.get = ctor.prototype._getter;
+
+    // setter void (unsigned long index, type value);
+    ctor.prototype._setter = function(index, value) {
+      if (arguments.length < 2) throw new SyntaxError("Not enough arguments");
+
+      index = ECMAScript.ToUint32(index);
+      if (index >= this.length) {
+        return undefined;
+      }
+
+      var bytes = this._pack(value), i, o;
+      for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT;
+           i < this.BYTES_PER_ELEMENT;
+           i += 1, o += 1) {
+        this.buffer._bytes[o] = bytes[i];
+      }
+    };
+
+    // void set(TypedArray array, optional unsigned long offset);
+    // void set(sequence<type> array, optional unsigned long offset);
+    ctor.prototype.set = function(index, value) {
+      if (arguments.length < 1) throw new SyntaxError("Not enough arguments");
+      var array, sequence, offset, len,
+          i, s, d,
+          byteOffset, byteLength, tmp;
+
+      if (typeof arguments[0] === 'object' && arguments[0].constructor === this.constructor) {
+        // void set(TypedArray array, optional unsigned long offset);
+        array = arguments[0];
+        offset = ECMAScript.ToUint32(arguments[1]);
+
+        if (offset + array.length > this.length) {
+          throw new RangeError("Offset plus length of array is out of range");
+        }
+
+        byteOffset = this.byteOffset + offset * this.BYTES_PER_ELEMENT;
+        byteLength = array.length * this.BYTES_PER_ELEMENT;
+
+        if (array.buffer === this.buffer) {
+          tmp = [];
+          for (i = 0, s = array.byteOffset; i < byteLength; i += 1, s += 1) {
+            tmp[i] = array.buffer._bytes[s];
+          }
+          for (i = 0, d = byteOffset; i < byteLength; i += 1, d += 1) {
+            this.buffer._bytes[d] = tmp[i];
+          }
+        } else {
+          for (i = 0, s = array.byteOffset, d = byteOffset;
+               i < byteLength; i += 1, s += 1, d += 1) {
+            this.buffer._bytes[d] = array.buffer._bytes[s];
+          }
+        }
+      } else if (typeof arguments[0] === 'object' && typeof arguments[0].length !== 'undefined') {
+        // void set(sequence<type> array, optional unsigned long offset);
+        sequence = arguments[0];
+        len = ECMAScript.ToUint32(sequence.length);
+        offset = ECMAScript.ToUint32(arguments[1]);
+
+        if (offset + len > this.length) {
+          throw new RangeError("Offset plus length of array is out of range");
+        }
+
+        for (i = 0; i < len; i += 1) {
+          s = sequence[i];
+          this._setter(offset + i, Number(s));
+        }
+      } else {
+        throw new TypeError("Unexpected argument type(s)");
+      }
+    };
+
+    // TypedArray subarray(long begin, optional long end);
+    ctor.prototype.subarray = function(start, end) {
+      function clamp(v, min, max) { return v < min ? min : v > max ? max : v; }
+
+      start = ECMAScript.ToInt32(start);
+      end = ECMAScript.ToInt32(end);
+
+      if (arguments.length < 1) { start = 0; }
+      if (arguments.length < 2) { end = this.length; }
+
+      if (start < 0) { start = this.length + start; }
+      if (end < 0) { end = this.length + end; }
+
+      start = clamp(start, 0, this.length);
+      end = clamp(end, 0, this.length);
+
+      var len = end - start;
+      if (len < 0) {
+        len = 0;
+      }
+
+      return new this.constructor(
+        this.buffer, this.byteOffset + start * this.BYTES_PER_ELEMENT, len);
+    };
+
+    return ctor;
+  }
+
+  var Int8Array = makeConstructor(1, packI8, unpackI8);
+  var Uint8Array = makeConstructor(1, packU8, unpackU8);
+  var Uint8ClampedArray = makeConstructor(1, packU8Clamped, unpackU8);
+  var Int16Array = makeConstructor(2, packI16, unpackI16);
+  var Uint16Array = makeConstructor(2, packU16, unpackU16);
+  var Int32Array = makeConstructor(4, packI32, unpackI32);
+  var Uint32Array = makeConstructor(4, packU32, unpackU32);
+  var Float32Array = makeConstructor(4, packF32, unpackF32);
+  var Float64Array = makeConstructor(8, packF64, unpackF64);
+
+  exports.Int8Array = exports.Int8Array || Int8Array;
+  exports.Uint8Array = exports.Uint8Array || Uint8Array;
+  exports.Uint8ClampedArray = exports.Uint8ClampedArray || Uint8ClampedArray;
+  exports.Int16Array = exports.Int16Array || Int16Array;
+  exports.Uint16Array = exports.Uint16Array || Uint16Array;
+  exports.Int32Array = exports.Int32Array || Int32Array;
+  exports.Uint32Array = exports.Uint32Array || Uint32Array;
+  exports.Float32Array = exports.Float32Array || Float32Array;
+  exports.Float64Array = exports.Float64Array || Float64Array;
+}());
+
+//
+// 6 The DataView View Type
+//
+
+(function() {
+  function r(array, index) {
+    return ECMAScript.IsCallable(array.get) ? array.get(index) : array[index];
+  }
+
+  var IS_BIG_ENDIAN = (function() {
+    var u16array = new(exports.Uint16Array)([0x1234]),
+        u8array = new(exports.Uint8Array)(u16array.buffer);
+    return r(u8array, 0) === 0x12;
+  }());
+
+  // Constructor(ArrayBuffer buffer,
+  //             optional unsigned long byteOffset,
+  //             optional unsigned long byteLength)
+  /** @constructor */
+  var DataView = function DataView(buffer, byteOffset, byteLength) {
+    if (arguments.length === 0) {
+      buffer = new exports.ArrayBuffer(0);
+    } else if (!(buffer instanceof exports.ArrayBuffer || ECMAScript.Class(buffer) === 'ArrayBuffer')) {
+      throw new TypeError("TypeError");
+    }
+
+    this.buffer = buffer || new exports.ArrayBuffer(0);
+
+    this.byteOffset = ECMAScript.ToUint32(byteOffset);
+    if (this.byteOffset > this.buffer.byteLength) {
+      throw new RangeError("byteOffset out of range");
+    }
+
+    if (arguments.length < 3) {
+      this.byteLength = this.buffer.byteLength - this.byteOffset;
+    } else {
+      this.byteLength = ECMAScript.ToUint32(byteLength);
+    }
+
+    if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) {
+      throw new RangeError("byteOffset and length reference an area beyond the end of the buffer");
+    }
+
+    configureProperties(this);
+  };
+
+  function makeGetter(arrayType) {
+    return function(byteOffset, littleEndian) {
+
+      byteOffset = ECMAScript.ToUint32(byteOffset);
+
+      if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) {
+        throw new RangeError("Array index out of range");
+      }
+      byteOffset += this.byteOffset;
+
+      var uint8Array = new exports.Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT),
+          bytes = [], i;
+      for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) {
+        bytes.push(r(uint8Array, i));
+      }
+
+      if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) {
+        bytes.reverse();
+      }
+
+      return r(new arrayType(new exports.Uint8Array(bytes).buffer), 0);
+    };
+  }
+
+  DataView.prototype.getUint8 = makeGetter(exports.Uint8Array);
+  DataView.prototype.getInt8 = makeGetter(exports.Int8Array);
+  DataView.prototype.getUint16 = makeGetter(exports.Uint16Array);
+  DataView.prototype.getInt16 = makeGetter(exports.Int16Array);
+  DataView.prototype.getUint32 = makeGetter(exports.Uint32Array);
+  DataView.prototype.getInt32 = makeGetter(exports.Int32Array);
+  DataView.prototype.getFloat32 = makeGetter(exports.Float32Array);
+  DataView.prototype.getFloat64 = makeGetter(exports.Float64Array);
+
+  function makeSetter(arrayType) {
+    return function(byteOffset, value, littleEndian) {
+
+      byteOffset = ECMAScript.ToUint32(byteOffset);
+      if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) {
+        throw new RangeError("Array index out of range");
+      }
+
+      // Get bytes
+      var typeArray = new arrayType([value]),
+          byteArray = new exports.Uint8Array(typeArray.buffer),
+          bytes = [], i, byteView;
+
+      for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) {
+        bytes.push(r(byteArray, i));
+      }
+
+      // Flip if necessary
+      if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) {
+        bytes.reverse();
+      }
+
+      // Write them
+      byteView = new exports.Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT);
+      byteView.set(bytes);
+    };
+  }
+
+  DataView.prototype.setUint8 = makeSetter(exports.Uint8Array);
+  DataView.prototype.setInt8 = makeSetter(exports.Int8Array);
+  DataView.prototype.setUint16 = makeSetter(exports.Uint16Array);
+  DataView.prototype.setInt16 = makeSetter(exports.Int16Array);
+  DataView.prototype.setUint32 = makeSetter(exports.Uint32Array);
+  DataView.prototype.setInt32 = makeSetter(exports.Int32Array);
+  DataView.prototype.setFloat32 = makeSetter(exports.Float32Array);
+  DataView.prototype.setFloat64 = makeSetter(exports.Float64Array);
+
+  exports.DataView = exports.DataView || DataView;
+
+}());
diff --git a/node_modules/typedarray/package.json b/node_modules/typedarray/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..a7854a0fc5fb420607f8519afbbf588597f0628e
--- /dev/null
+++ b/node_modules/typedarray/package.json
@@ -0,0 +1,55 @@
+{
+  "name": "typedarray",
+  "version": "0.0.6",
+  "description": "TypedArray polyfill for old browsers",
+  "main": "index.js",
+  "devDependencies": {
+    "tape": "~2.3.2"
+  },
+  "scripts": {
+    "test": "tape test/*.js test/server/*.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/substack/typedarray.git"
+  },
+  "homepage": "https://github.com/substack/typedarray",
+  "keywords": [
+    "ArrayBuffer",
+    "DataView",
+    "Float32Array",
+    "Float64Array",
+    "Int8Array",
+    "Int16Array",
+    "Int32Array",
+    "Uint8Array",
+    "Uint8ClampedArray",
+    "Uint16Array",
+    "Uint32Array",
+    "typed",
+    "array",
+    "polyfill"
+  ],
+  "author": {
+    "name": "James Halliday",
+    "email": "mail@substack.net",
+    "url": "http://substack.net"
+  },
+  "license": "MIT",
+  "testling": {
+    "files": "test/*.js",
+    "browsers": [
+      "ie/6..latest",
+      "firefox/16..latest",
+      "firefox/nightly",
+      "chrome/22..latest",
+      "chrome/canary",
+      "opera/12..latest",
+      "opera/next",
+      "safari/5.1..latest",
+      "ipad/6.0..latest",
+      "iphone/6.0..latest",
+      "android-browser/4.2..latest"
+    ]
+  }
+}
diff --git a/node_modules/typedarray/readme.markdown b/node_modules/typedarray/readme.markdown
new file mode 100644
index 0000000000000000000000000000000000000000..d18f6f7197e6a5d852c592ba7539d58e9e4ea729
--- /dev/null
+++ b/node_modules/typedarray/readme.markdown
@@ -0,0 +1,61 @@
+# typedarray
+
+TypedArray polyfill ripped from [this
+module](https://raw.github.com/inexorabletash/polyfill).
+
+[![build status](https://secure.travis-ci.org/substack/typedarray.png)](http://travis-ci.org/substack/typedarray)
+
+[![testling badge](https://ci.testling.com/substack/typedarray.png)](https://ci.testling.com/substack/typedarray)
+
+# example
+
+``` js
+var Uint8Array = require('typedarray').Uint8Array;
+var ua = new Uint8Array(5);
+ua[1] = 256 + 55;
+console.log(ua[1]);
+```
+
+output:
+
+```
+55
+```
+
+# methods
+
+``` js
+var TA = require('typedarray')
+```
+
+The `TA` object has the following constructors:
+
+* TA.ArrayBuffer
+* TA.DataView
+* TA.Float32Array
+* TA.Float64Array
+* TA.Int8Array
+* TA.Int16Array
+* TA.Int32Array
+* TA.Uint8Array
+* TA.Uint8ClampedArray
+* TA.Uint16Array
+* TA.Uint32Array
+
+# install
+
+With [npm](https://npmjs.org) do:
+
+```
+npm install typedarray
+```
+
+To use this module in the browser, compile with
+[browserify](http://browserify.org)
+or download a UMD build from browserify CDN:
+
+http://wzrd.in/standalone/typedarray@latest
+
+# license
+
+MIT
diff --git a/node_modules/typedarray/test/server/undef_globals.js b/node_modules/typedarray/test/server/undef_globals.js
new file mode 100644
index 0000000000000000000000000000000000000000..425950f9fc9ed7c09d78c749f27014cfdf4a84d3
--- /dev/null
+++ b/node_modules/typedarray/test/server/undef_globals.js
@@ -0,0 +1,19 @@
+var test = require('tape');
+var vm = require('vm');
+var fs = require('fs');
+var src = fs.readFileSync(__dirname + '/../../index.js', 'utf8');
+
+test('u8a without globals', function (t) {
+    var c = {
+        module: { exports: {} },
+    };
+    c.exports = c.module.exports;
+    vm.runInNewContext(src, c);
+    var TA = c.module.exports;
+    var ua = new(TA.Uint8Array)(5);
+    
+    t.equal(ua.length, 5);
+    ua[1] = 256 + 55;
+    t.equal(ua[1], 55);
+    t.end();
+});
diff --git a/node_modules/typedarray/test/tarray.js b/node_modules/typedarray/test/tarray.js
new file mode 100644
index 0000000000000000000000000000000000000000..df596a34f23c0ef931cd5b41139985b8d23e8e2f
--- /dev/null
+++ b/node_modules/typedarray/test/tarray.js
@@ -0,0 +1,10 @@
+var TA = require('../');
+var test = require('tape');
+
+test('tiny u8a test', function (t) {
+    var ua = new(TA.Uint8Array)(5);
+    t.equal(ua.length, 5);
+    ua[1] = 256 + 55;
+    t.equal(ua[1], 55);
+    t.end();
+});
diff --git a/node_modules/xtend/.jshintrc b/node_modules/xtend/.jshintrc
new file mode 100644
index 0000000000000000000000000000000000000000..77887b5f0f2efc24bd55430cb6f95f8a0cad89d8
--- /dev/null
+++ b/node_modules/xtend/.jshintrc
@@ -0,0 +1,30 @@
+{
+    "maxdepth": 4,
+    "maxstatements": 200,
+    "maxcomplexity": 12,
+    "maxlen": 80,
+    "maxparams": 5,
+
+    "curly": true,
+    "eqeqeq": true,
+    "immed": true,
+    "latedef": false,
+    "noarg": true,
+    "noempty": true,
+    "nonew": true,
+    "undef": true,
+    "unused": "vars",
+    "trailing": true,
+
+    "quotmark": true,
+    "expr": true,
+    "asi": true,
+
+    "browser": false,
+    "esnext": true,
+    "devel": false,
+    "node": false,
+    "nonstandard": false,
+
+    "predef": ["require", "module", "__dirname", "__filename"]
+}
diff --git a/node_modules/escape-string-regexp/license b/node_modules/xtend/LICENSE
similarity index 93%
rename from node_modules/escape-string-regexp/license
rename to node_modules/xtend/LICENSE
index 654d0bfe943437d43242325b1fbcff5f400d84ee..0099f4f6c77f40ac409076408ad07449ffe246d3 100644
--- a/node_modules/escape-string-regexp/license
+++ b/node_modules/xtend/LICENSE
@@ -1,6 +1,5 @@
 The MIT License (MIT)
-
-Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
+Copyright (c) 2012-2014 Raynos.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/node_modules/xtend/README.md b/node_modules/xtend/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4a2703cff276b155e89c3abb7b09fbdfe90273f4
--- /dev/null
+++ b/node_modules/xtend/README.md
@@ -0,0 +1,32 @@
+# xtend
+
+[![browser support][3]][4]
+
+[![locked](http://badges.github.io/stability-badges/dist/locked.svg)](http://github.com/badges/stability-badges)
+
+Extend like a boss
+
+xtend is a basic utility library which allows you to extend an object by appending all of the properties from each object in a list. When there are identical properties, the right-most property takes precedence.
+
+## Examples
+
+```js
+var extend = require("xtend")
+
+// extend returns a new object. Does not mutate arguments
+var combination = extend({
+    a: "a",
+    b: "c"
+}, {
+    b: "b"
+})
+// { a: "a", b: "b" }
+```
+
+## Stability status: Locked
+
+## MIT Licensed 
+
+
+  [3]: http://ci.testling.com/Raynos/xtend.png
+  [4]: http://ci.testling.com/Raynos/xtend
diff --git a/node_modules/xtend/immutable.js b/node_modules/xtend/immutable.js
new file mode 100644
index 0000000000000000000000000000000000000000..94889c9de11a181cec153de1713c8ae14ae4cb43
--- /dev/null
+++ b/node_modules/xtend/immutable.js
@@ -0,0 +1,19 @@
+module.exports = extend
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function extend() {
+    var target = {}
+
+    for (var i = 0; i < arguments.length; i++) {
+        var source = arguments[i]
+
+        for (var key in source) {
+            if (hasOwnProperty.call(source, key)) {
+                target[key] = source[key]
+            }
+        }
+    }
+
+    return target
+}
diff --git a/node_modules/xtend/mutable.js b/node_modules/xtend/mutable.js
new file mode 100644
index 0000000000000000000000000000000000000000..72debede6ca58592fe93b5ab22d434311a76861b
--- /dev/null
+++ b/node_modules/xtend/mutable.js
@@ -0,0 +1,17 @@
+module.exports = extend
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function extend(target) {
+    for (var i = 1; i < arguments.length; i++) {
+        var source = arguments[i]
+
+        for (var key in source) {
+            if (hasOwnProperty.call(source, key)) {
+                target[key] = source[key]
+            }
+        }
+    }
+
+    return target
+}
diff --git a/node_modules/xtend/package.json b/node_modules/xtend/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..f7a39d10af5f5ea48fcd948e72ba6af62e372d39
--- /dev/null
+++ b/node_modules/xtend/package.json
@@ -0,0 +1,55 @@
+{
+  "name": "xtend",
+  "version": "4.0.2",
+  "description": "extend like a boss",
+  "keywords": [
+    "extend",
+    "merge",
+    "options",
+    "opts",
+    "object",
+    "array"
+  ],
+  "author": "Raynos <raynos2@gmail.com>",
+  "repository": "git://github.com/Raynos/xtend.git",
+  "main": "immutable",
+  "scripts": {
+    "test": "node test"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "tape": "~1.1.0"
+  },
+  "homepage": "https://github.com/Raynos/xtend",
+  "contributors": [
+    {
+      "name": "Jake Verbaten"
+    },
+    {
+      "name": "Matt Esch"
+    }
+  ],
+  "bugs": {
+    "url": "https://github.com/Raynos/xtend/issues",
+    "email": "raynos2@gmail.com"
+  },
+  "license": "MIT",
+  "testling": {
+    "files": "test.js",
+    "browsers": [
+      "ie/7..latest",
+      "firefox/16..latest",
+      "firefox/nightly",
+      "chrome/22..latest",
+      "chrome/canary",
+      "opera/12..latest",
+      "opera/next",
+      "safari/5.1..latest",
+      "ipad/6.0..latest",
+      "iphone/6.0..latest"
+    ]
+  },
+  "engines": {
+    "node": ">=0.4"
+  }
+}
diff --git a/node_modules/xtend/test.js b/node_modules/xtend/test.js
new file mode 100644
index 0000000000000000000000000000000000000000..b895b42b3f76804de7ee2ef0231a3343b2f461b3
--- /dev/null
+++ b/node_modules/xtend/test.js
@@ -0,0 +1,103 @@
+var test = require("tape")
+var extend = require("./")
+var mutableExtend = require("./mutable")
+
+test("merge", function(assert) {
+    var a = { a: "foo" }
+    var b = { b: "bar" }
+
+    assert.deepEqual(extend(a, b), { a: "foo", b: "bar" })
+    assert.end()
+})
+
+test("replace", function(assert) {
+    var a = { a: "foo" }
+    var b = { a: "bar" }
+
+    assert.deepEqual(extend(a, b), { a: "bar" })
+    assert.end()
+})
+
+test("undefined", function(assert) {
+    var a = { a: undefined }
+    var b = { b: "foo" }
+
+    assert.deepEqual(extend(a, b), { a: undefined, b: "foo" })
+    assert.deepEqual(extend(b, a), { a: undefined, b: "foo" })
+    assert.end()
+})
+
+test("handle 0", function(assert) {
+    var a = { a: "default" }
+    var b = { a: 0 }
+
+    assert.deepEqual(extend(a, b), { a: 0 })
+    assert.deepEqual(extend(b, a), { a: "default" })
+    assert.end()
+})
+
+test("is immutable", function (assert) {
+    var record = {}
+
+    extend(record, { foo: "bar" })
+    assert.equal(record.foo, undefined)
+    assert.end()
+})
+
+test("null as argument", function (assert) {
+    var a = { foo: "bar" }
+    var b = null
+    var c = void 0
+
+    assert.deepEqual(extend(b, a, c), { foo: "bar" })
+    assert.end()
+})
+
+test("mutable", function (assert) {
+    var a = { foo: "bar" }
+
+    mutableExtend(a, { bar: "baz" })
+
+    assert.equal(a.bar, "baz")
+    assert.end()
+})
+
+test("null prototype", function(assert) {
+    var a = { a: "foo" }
+    var b = Object.create(null)
+    b.b = "bar";
+
+    assert.deepEqual(extend(a, b), { a: "foo", b: "bar" })
+    assert.end()
+})
+
+test("null prototype mutable", function (assert) {
+    var a = { foo: "bar" }
+    var b = Object.create(null)
+    b.bar = "baz";
+
+    mutableExtend(a, b)
+
+    assert.equal(a.bar, "baz")
+    assert.end()
+})
+
+test("prototype pollution", function (assert) {
+    var a = {}
+    var maliciousPayload = '{"__proto__":{"oops":"It works!"}}'
+
+    assert.strictEqual(a.oops, undefined)
+    extend({}, maliciousPayload)
+    assert.strictEqual(a.oops, undefined)
+    assert.end()
+})
+
+test("prototype pollution mutable", function (assert) {
+    var a = {}
+    var maliciousPayload = '{"__proto__":{"oops":"It works!"}}'
+
+    assert.strictEqual(a.oops, undefined)
+    mutableExtend({}, maliciousPayload)
+    assert.strictEqual(a.oops, undefined)
+    assert.end()
+})
diff --git a/package-lock.json b/package-lock.json
index 654aa55201c2ac47071ff4d878aef5cda064d111..5cdcb4d35a28240968afe2ddb5a26bc48a3c589b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,6 +16,7 @@
         "express-sanitizer": "^1.0.6",
         "express-session": "^1.17.3",
         "express-validator": "^6.14.2",
+        "multer": "^1.4.5-lts.1",
         "mysql": "^2.18.1",
         "pug": "^3.0.2",
         "req": "^0.1.4",
@@ -141,16 +142,24 @@
       }
     },
     "node_modules/ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
       "dependencies": {
-        "color-convert": "^1.9.0"
+        "color-convert": "^2.0.1"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
       }
     },
+    "node_modules/append-field": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
+      "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
+    },
     "node_modules/aproba": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
@@ -197,9 +206,9 @@
       "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw=="
     },
     "node_modules/async": {
-      "version": "0.9.2",
-      "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
-      "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
+      "version": "3.2.4",
+      "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+      "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
     },
     "node_modules/babel-walk": {
       "version": "3.0.0-canary-5",
@@ -270,6 +279,22 @@
         "concat-map": "0.0.1"
       }
     },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+    },
+    "node_modules/busboy": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+      "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+      "dependencies": {
+        "streamsearch": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=10.16.0"
+      }
+    },
     "node_modules/bytes": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -291,16 +316,18 @@
       }
     },
     "node_modules/chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
       "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
     "node_modules/character-parser": {
@@ -320,17 +347,20 @@
       }
     },
     "node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
       "dependencies": {
-        "color-name": "1.1.3"
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
       }
     },
     "node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
     },
     "node_modules/color-support": {
       "version": "1.1.3",
@@ -345,6 +375,20 @@
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
+    "node_modules/concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "engines": [
+        "node >= 0.8"
+      ],
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
     "node_modules/console-control-strings": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -464,11 +508,11 @@
       "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
     },
     "node_modules/ejs": {
-      "version": "3.1.6",
-      "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
-      "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
+      "version": "3.1.9",
+      "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
+      "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
       "dependencies": {
-        "jake": "^10.6.1"
+        "jake": "^10.8.5"
       },
       "bin": {
         "ejs": "bin/cli.js"
@@ -495,14 +539,6 @@
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
       "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
     },
-    "node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
     "node_modules/etag": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -640,11 +676,30 @@
       ]
     },
     "node_modules/filelist": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
-      "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+      "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
       "dependencies": {
-        "minimatch": "^3.0.4"
+        "minimatch": "^5.0.1"
+      }
+    },
+    "node_modules/filelist/node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/filelist/node_modules/minimatch": {
+      "version": "5.1.6",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+      "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=10"
       }
     },
     "node_modules/finalhandler": {
@@ -764,11 +819,11 @@
       }
     },
     "node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
       }
     },
     "node_modules/has-symbols": {
@@ -936,12 +991,12 @@
       "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
     },
     "node_modules/jake": {
-      "version": "10.8.2",
-      "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
-      "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
+      "version": "10.8.5",
+      "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+      "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
       "dependencies": {
-        "async": "0.9.x",
-        "chalk": "^2.4.2",
+        "async": "^3.2.3",
+        "chalk": "^4.0.2",
         "filelist": "^1.0.1",
         "minimatch": "^3.0.4"
       },
@@ -949,7 +1004,7 @@
         "jake": "bin/cli.js"
       },
       "engines": {
-        "node": "*"
+        "node": ">=10"
       }
     },
     "node_modules/js-stringify": {
@@ -1066,6 +1121,14 @@
         "node": "*"
       }
     },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/minipass": {
       "version": "3.3.4",
       "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz",
@@ -1105,6 +1168,34 @@
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
     },
+    "node_modules/multer": {
+      "version": "1.4.5-lts.1",
+      "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
+      "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
+      "dependencies": {
+        "append-field": "^1.0.0",
+        "busboy": "^1.0.0",
+        "concat-stream": "^1.5.2",
+        "mkdirp": "^0.5.4",
+        "object-assign": "^4.1.1",
+        "type-is": "^1.6.4",
+        "xtend": "^4.0.0"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/multer/node_modules/mkdirp": {
+      "version": "0.5.6",
+      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+      "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+      "dependencies": {
+        "minimist": "^1.2.6"
+      },
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      }
+    },
     "node_modules/mysql": {
       "version": "2.18.1",
       "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
@@ -1631,6 +1722,14 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/streamsearch": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+      "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
     "node_modules/string_decoder": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -1664,14 +1763,14 @@
       }
     },
     "node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
       "dependencies": {
-        "has-flag": "^3.0.0"
+        "has-flag": "^4.0.0"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=8"
       }
     },
     "node_modules/tar": {
@@ -1728,6 +1827,11 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+    },
     "node_modules/uid-safe": {
       "version": "2.1.5",
       "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
@@ -1833,6 +1937,14 @@
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
     },
+    "node_modules/xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+      "engines": {
+        "node": ">=0.4"
+      }
+    },
     "node_modules/yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
@@ -1923,13 +2035,18 @@
       "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
     },
     "ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
       "requires": {
-        "color-convert": "^1.9.0"
+        "color-convert": "^2.0.1"
       }
     },
+    "append-field": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
+      "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
+    },
     "aproba": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
@@ -1972,9 +2089,9 @@
       "integrity": "sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw=="
     },
     "async": {
-      "version": "0.9.2",
-      "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
-      "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
+      "version": "3.2.4",
+      "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+      "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
     },
     "babel-walk": {
       "version": "3.0.0-canary-5",
@@ -2031,6 +2148,19 @@
         "concat-map": "0.0.1"
       }
     },
+    "buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+    },
+    "busboy": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+      "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+      "requires": {
+        "streamsearch": "^1.1.0"
+      }
+    },
     "bytes": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@@ -2046,13 +2176,12 @@
       }
     },
     "chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
       "requires": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
       }
     },
     "character-parser": {
@@ -2069,17 +2198,17 @@
       "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
     },
     "color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
       "requires": {
-        "color-name": "1.1.3"
+        "color-name": "~1.1.4"
       }
     },
     "color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
     },
     "color-support": {
       "version": "1.1.3",
@@ -2091,6 +2220,17 @@
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
       "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
     },
+    "concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "requires": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
     "console-control-strings": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -2179,11 +2319,11 @@
       "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
     },
     "ejs": {
-      "version": "3.1.6",
-      "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
-      "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
+      "version": "3.1.9",
+      "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
+      "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
       "requires": {
-        "jake": "^10.6.1"
+        "jake": "^10.8.5"
       }
     },
     "emoji-regex": {
@@ -2201,11 +2341,6 @@
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
       "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
     },
-    "escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
-    },
     "etag": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -2301,11 +2436,29 @@
       }
     },
     "filelist": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
-      "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+      "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
       "requires": {
-        "minimatch": "^3.0.4"
+        "minimatch": "^5.0.1"
+      },
+      "dependencies": {
+        "brace-expansion": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+          "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+          "requires": {
+            "balanced-match": "^1.0.0"
+          }
+        },
+        "minimatch": {
+          "version": "5.1.6",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+          "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+          "requires": {
+            "brace-expansion": "^2.0.1"
+          }
+        }
       }
     },
     "finalhandler": {
@@ -2398,9 +2551,9 @@
       }
     },
     "has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
     },
     "has-symbols": {
       "version": "1.0.2",
@@ -2525,12 +2678,12 @@
       "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
     },
     "jake": {
-      "version": "10.8.2",
-      "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
-      "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
+      "version": "10.8.5",
+      "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
+      "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
       "requires": {
-        "async": "0.9.x",
-        "chalk": "^2.4.2",
+        "async": "^3.2.3",
+        "chalk": "^4.0.2",
         "filelist": "^1.0.1",
         "minimatch": "^3.0.4"
       }
@@ -2618,6 +2771,11 @@
         "brace-expansion": "^1.1.7"
       }
     },
+    "minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
+    },
     "minipass": {
       "version": "3.3.4",
       "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz",
@@ -2645,6 +2803,30 @@
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
       "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
     },
+    "multer": {
+      "version": "1.4.5-lts.1",
+      "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
+      "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
+      "requires": {
+        "append-field": "^1.0.0",
+        "busboy": "^1.0.0",
+        "concat-stream": "^1.5.2",
+        "mkdirp": "^0.5.4",
+        "object-assign": "^4.1.1",
+        "type-is": "^1.6.4",
+        "xtend": "^4.0.0"
+      },
+      "dependencies": {
+        "mkdirp": {
+          "version": "0.5.6",
+          "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+          "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+          "requires": {
+            "minimist": "^1.2.6"
+          }
+        }
+      }
+    },
     "mysql": {
       "version": "2.18.1",
       "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
@@ -3070,6 +3252,11 @@
       "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
       "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
     },
+    "streamsearch": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+      "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="
+    },
     "string_decoder": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -3097,11 +3284,11 @@
       }
     },
     "supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
       "requires": {
-        "has-flag": "^3.0.0"
+        "has-flag": "^4.0.0"
       }
     },
     "tar": {
@@ -3146,6 +3333,11 @@
         "mime-types": "~2.1.24"
       }
     },
+    "typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+    },
     "uid-safe": {
       "version": "2.1.5",
       "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
@@ -3227,6 +3419,11 @@
       "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
       "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
     },
+    "xtend": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+      "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+    },
     "yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
diff --git a/package.json b/package.json
index 770d01de95f0a3d88ef9ea8b4841642f0d06b1b3..6568342b6e3fdc1ebf5a4fb802ef7927b54eccc7 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
     "express-sanitizer": "^1.0.6",
     "express-session": "^1.17.3",
     "express-validator": "^6.14.2",
+    "multer": "^1.4.5-lts.1",
     "mysql": "^2.18.1",
     "pug": "^3.0.2",
     "req": "^0.1.4",
diff --git a/views/index.ejs b/views/index.ejs
index aedcf1be5d0badd62657fc336ce505df2cf4400a..dff6b66197b6b965ba9b445b432ccecb434ba619 100644
--- a/views/index.ejs
+++ b/views/index.ejs
@@ -10,9 +10,10 @@
       <a href="/."> <img src = "/public/logo.png" class ="logo" alt = ""> </a>
     <div>
       <ul id="navbar"> 
-        <li><a href="about">About <%=shopName%></a></li>
-        <li><a href="search">Search for items</a></li>
-        <li><a href="register">Register with us</a></li>
+        <li><a href="about">About </a></li>
+        <li><a href="search">Search </a></li>
+        <li><a href="itemlist">List </a></li>
+        <li><a href="register">Register </a></li>
         <li><a href="login">Login</a></li>
         <li><a href="logout">Logout</a></li>
       </ul>
@@ -64,6 +65,11 @@
 
   </section>
 
+  <section id = ""> 
+
+  </section>
+
+
 
 
 
diff --git a/views/itemlist.ejs b/views/itemlist.ejs
new file mode 100644
index 0000000000000000000000000000000000000000..40c9d11711d256c981179f8f6781fa3f579f472e
--- /dev/null
+++ b/views/itemlist.ejs
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+  <head>
+    <title> List on <%=shopName%></title>
+    <link rel="stylesheet"  type="text/css" href="main.css" />
+  </head>
+  <body>
+    <h1>List on <%=shopName%></h1>
+
+    <form method ="POST" enctype="multipart/form-data" action = "photoDB">
+        <input type = "text" placeholder="Title of product" name = "title">
+        <input type = "text" placeholder="Name of product" name = "name">
+        <input type = "text" placeholder="Cost of shipping" name = "price">
+        <input type = "text" placeholder="Information" name = "info">
+        <input type = "text" placeholder="Condition of product" name = "condition">
+        <input type = "file" name = "ProductImage">
+        <button class = "button"> List </button>
+    </form>
+
+
+    <!-- Redirects to home page -->
+    <p><a href="/">home page</a></p>
+  </body>
+</html>
\ No newline at end of file
diff --git a/views/itemlisted.ejs b/views/itemlisted.ejs
new file mode 100644
index 0000000000000000000000000000000000000000..d58573732eb78a647acb08c0e740e6e92a69b768
--- /dev/null
+++ b/views/itemlisted.ejs
@@ -0,0 +1,13 @@
+<!doctype html>
+<html>
+  <head>
+    <title>About <%=shopName%></title>
+    <link rel="stylesheet"  type="text/css" href="main.css" />
+  </head>
+  <body>
+    <h1>About <%=shopName%></h1>
+    <p>We sell all sorts of  and nothing else!</p>
+    <!-- Redirects to home page -->
+    <p><a href="/">home page</a></p>
+  </body>
+</html>
\ No newline at end of file
diff --git a/views/login.ejs b/views/login.ejs
index 7abdb9c8c5ed163b0e36a24c1ada12ac24e6948f..2c0bb83195c90243813df8d192900603ea3859b2 100644
--- a/views/login.ejs
+++ b/views/login.ejs
@@ -5,7 +5,7 @@
     <link rel="stylesheet"  type="text/css" href="main.css" />
   </head>
   <body>
-    <h1>Login for <%=shopName%></h1>
+    <h2>Login for <%=shopName%></h2>
     <form method="POST" action="/loggedin">
         <p>Username: <input id="username" type="username" name="username" value="" /></p>
         <p>Password: <input id="password" type="password" name="password" value="" /></p>