+
+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/express-session/README.md b/node_modules/express-session/README.md
new file mode 100644
index 00000000..b880e6b4
--- /dev/null
+++ b/node_modules/express-session/README.md
@@ -0,0 +1,1032 @@
+# express-session
+
+[![NPM Version][npm-version-image]][npm-url]
+[![NPM Downloads][npm-downloads-image]][node-url]
+[![Build Status][ci-image]][ci-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install express-session
+```
+
+## API
+
+```js
+var session = require('express-session')
+```
+
+### session(options)
+
+Create a session middleware with the given `options`.
+
+**Note** Session data is _not_ saved in the cookie itself, just the session ID.
+Session data is stored server-side.
+
+**Note** Since version 1.5.0, the [`cookie-parser` middleware](https://www.npmjs.com/package/cookie-parser)
+no longer needs to be used for this module to work. This module now directly reads
+and writes cookies on `req`/`res`. Using `cookie-parser` may result in issues
+if the `secret` is not the same between this module and `cookie-parser`.
+
+**Warning** The default server-side session storage, `MemoryStore`, is _purposely_
+not designed for a production environment. It will leak memory under most
+conditions, does not scale past a single process, and is meant for debugging and
+developing.
+
+For a list of stores, see [compatible session stores](#compatible-session-stores).
+
+#### Options
+
+`express-session` accepts these properties in the options object.
+
+##### cookie
+
+Settings object for the session ID cookie. The default value is
+`{ path: '/', httpOnly: true, secure: false, maxAge: null }`.
+
+The following are options that can be set in this object.
+
+##### cookie.domain
+
+Specifies the value for the `Domain` `Set-Cookie` attribute. By default, no domain
+is set, and most clients will consider the cookie to apply to only the current
+domain.
+
+##### cookie.expires
+
+Specifies the `Date` object to be the value for the `Expires` `Set-Cookie` attribute.
+By default, no expiration is set, and most clients will consider this a
+"non-persistent cookie" and will delete it on a condition like exiting a web browser
+application.
+
+**Note** If both `expires` and `maxAge` are set in the options, then the last one
+defined in the object is what is used.
+
+**Note** The `expires` option should not be set directly; instead only use the `maxAge`
+option.
+
+##### cookie.httpOnly
+
+Specifies the `boolean` value for the `HttpOnly` `Set-Cookie` attribute. When truthy,
+the `HttpOnly` attribute is set, otherwise it is not. By default, the `HttpOnly`
+attribute is set.
+
+**Note** be careful when setting this to `true`, as compliant clients will not allow
+client-side JavaScript to see the cookie in `document.cookie`.
+
+##### cookie.maxAge
+
+Specifies the `number` (in milliseconds) to use when calculating the `Expires`
+`Set-Cookie` attribute. This is done by taking the current server time and adding
+`maxAge` milliseconds to the value to calculate an `Expires` datetime. By default,
+no maximum age is set.
+
+**Note** If both `expires` and `maxAge` are set in the options, then the last one
+defined in the object is what is used.
+
+##### cookie.partitioned
+
+Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](rfc-cutler-httpbis-partitioned-cookies)
+attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not.
+By default, the `Partitioned` attribute is not set.
+
+**Note** This is an attribute that has not yet been fully standardized, and may
+change in the future. This also means many clients may ignore this attribute until
+they understand it.
+
+More information about can be found in [the proposal](https://github.com/privacycg/CHIPS).
+
+##### cookie.path
+
+Specifies the value for the `Path` `Set-Cookie`. By default, this is set to `'/'`, which
+is the root path of the domain.
+
+##### cookie.priority
+
+Specifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute][rfc-west-cookie-priority-00-4.1].
+
+ - `'low'` will set the `Priority` attribute to `Low`.
+ - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
+ - `'high'` will set the `Priority` attribute to `High`.
+
+More information about the different priority levels can be found in
+[the specification][rfc-west-cookie-priority-00-4.1].
+
+**Note** This is an attribute that has not yet been fully standardized, and may change in the future.
+This also means many clients may ignore this attribute until they understand it.
+
+##### cookie.sameSite
+
+Specifies the `boolean` or `string` to be the value for the `SameSite` `Set-Cookie` attribute.
+By default, this is `false`.
+
+ - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+ - `false` will not set the `SameSite` attribute.
+ - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
+ - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
+ - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+
+More information about the different enforcement levels can be found in
+[the specification][rfc-6265bis-03-4.1.2.7].
+
+**Note** This is an attribute that has not yet been fully standardized, and may change in
+the future. This also means many clients may ignore this attribute until they understand it.
+
+**Note** There is a [draft spec](https://tools.ietf.org/html/draft-west-cookie-incrementalism-01)
+that requires that the `Secure` attribute be set to `true` when the `SameSite` attribute has been
+set to `'none'`. Some web browsers or other clients may be adopting this specification.
+
+##### cookie.secure
+
+Specifies the `boolean` value for the `Secure` `Set-Cookie` attribute. When truthy,
+the `Secure` attribute is set, otherwise it is not. By default, the `Secure`
+attribute is not set.
+
+**Note** be careful when setting this to `true`, as compliant clients will not send
+the cookie back to the server in the future if the browser does not have an HTTPS
+connection.
+
+Please note that `secure: true` is a **recommended** option. However, it requires
+an https-enabled website, i.e., HTTPS is necessary for secure cookies. If `secure`
+is set, and you access your site over HTTP, the cookie will not be set. If you
+have your node.js behind a proxy and are using `secure: true`, you need to set
+"trust proxy" in express:
+
+```js
+var app = express()
+app.set('trust proxy', 1) // trust first proxy
+app.use(session({
+ secret: 'keyboard cat',
+ resave: false,
+ saveUninitialized: true,
+ cookie: { secure: true }
+}))
+```
+
+For using secure cookies in production, but allowing for testing in development,
+the following is an example of enabling this setup based on `NODE_ENV` in express:
+
+```js
+var app = express()
+var sess = {
+ secret: 'keyboard cat',
+ cookie: {}
+}
+
+if (app.get('env') === 'production') {
+ app.set('trust proxy', 1) // trust first proxy
+ sess.cookie.secure = true // serve secure cookies
+}
+
+app.use(session(sess))
+```
+
+The `cookie.secure` option can also be set to the special value `'auto'` to have
+this setting automatically match the determined security of the connection. Be
+careful when using this setting if the site is available both as HTTP and HTTPS,
+as once the cookie is set on HTTPS, it will no longer be visible over HTTP. This
+is useful when the Express `"trust proxy"` setting is properly setup to simplify
+development vs production configuration.
+
+##### genid
+
+Function to call to generate a new session ID. Provide a function that returns
+a string that will be used as a session ID. The function is given `req` as the
+first argument if you want to use some value attached to `req` when generating
+the ID.
+
+The default value is a function which uses the `uid-safe` library to generate IDs.
+
+**NOTE** be careful to generate unique IDs so your sessions do not conflict.
+
+```js
+app.use(session({
+ genid: function(req) {
+ return genuuid() // use UUIDs for session IDs
+ },
+ secret: 'keyboard cat'
+}))
+```
+
+##### name
+
+The name of the session ID cookie to set in the response (and read from in the
+request).
+
+The default value is `'connect.sid'`.
+
+**Note** if you have multiple apps running on the same hostname (this is just
+the name, i.e. `localhost` or `127.0.0.1`; different schemes and ports do not
+name a different hostname), then you need to separate the session cookies from
+each other. The simplest method is to simply set different `name`s per app.
+
+##### proxy
+
+Trust the reverse proxy when setting secure cookies (via the "X-Forwarded-Proto"
+header).
+
+The default value is `undefined`.
+
+ - `true` The "X-Forwarded-Proto" header will be used.
+ - `false` All headers are ignored and the connection is considered secure only
+ if there is a direct TLS/SSL connection.
+ - `undefined` Uses the "trust proxy" setting from express
+
+##### resave
+
+Forces the session to be saved back to the session store, even if the session
+was never modified during the request. Depending on your store this may be
+necessary, but it can also create race conditions where a client makes two
+parallel requests to your server and changes made to the session in one
+request may get overwritten when the other request ends, even if it made no
+changes (this behavior also depends on what store you're using).
+
+The default value is `true`, but using the default has been deprecated,
+as the default will change in the future. Please research into this setting
+and choose what is appropriate to your use-case. Typically, you'll want
+`false`.
+
+How do I know if this is necessary for my store? The best way to know is to
+check with your store if it implements the `touch` method. If it does, then
+you can safely set `resave: false`. If it does not implement the `touch`
+method and your store sets an expiration date on stored sessions, then you
+likely need `resave: true`.
+
+##### rolling
+
+Force the session identifier cookie to be set on every response. The expiration
+is reset to the original [`maxAge`](#cookiemaxage), resetting the expiration
+countdown.
+
+The default value is `false`.
+
+With this enabled, the session identifier cookie will expire in
+[`maxAge`](#cookiemaxage) since the last response was sent instead of in
+[`maxAge`](#cookiemaxage) since the session was last modified by the server.
+
+This is typically used in conjunction with short, non-session-length
+[`maxAge`](#cookiemaxage) values to provide a quick timeout of the session data
+with reduced potential of it occurring during on going server interactions.
+
+**Note** When this option is set to `true` but the `saveUninitialized` option is
+set to `false`, the cookie will not be set on a response with an uninitialized
+session. This option only modifies the behavior when an existing session was
+loaded for the request.
+
+##### saveUninitialized
+
+Forces a session that is "uninitialized" to be saved to the store. A session is
+uninitialized when it is new but not modified. Choosing `false` is useful for
+implementing login sessions, reducing server storage usage, or complying with
+laws that require permission before setting a cookie. Choosing `false` will also
+help with race conditions where a client makes multiple parallel requests
+without a session.
+
+The default value is `true`, but using the default has been deprecated, as the
+default will change in the future. Please research into this setting and
+choose what is appropriate to your use-case.
+
+**Note** if you are using Session in conjunction with PassportJS, Passport
+will add an empty Passport object to the session for use after a user is
+authenticated, which will be treated as a modification to the session, causing
+it to be saved. *This has been fixed in PassportJS 0.3.0*
+
+##### secret
+
+**Required option**
+
+This is the secret used to sign the session ID cookie. The secret can be any type
+of value that is supported by Node.js `crypto.createHmac` (like a string or a
+`Buffer`). This can be either a single secret, or an array of multiple secrets. If
+an array of secrets is provided, only the first element will be used to sign the
+session ID cookie, while all the elements will be considered when verifying the
+signature in requests. The secret itself should be not easily parsed by a human and
+would best be a random set of characters. A best practice may include:
+
+ - The use of environment variables to store the secret, ensuring the secret itself
+ does not exist in your repository.
+ - Periodic updates of the secret, while ensuring the previous secret is in the
+ array.
+
+Using a secret that cannot be guessed will reduce the ability to hijack a session to
+only guessing the session ID (as determined by the `genid` option).
+
+Changing the secret value will invalidate all existing sessions. In order to rotate
+the secret without invalidating sessions, provide an array of secrets, with the new
+secret as first element of the array, and including previous secrets as the later
+elements.
+
+**Note** HMAC-256 is used to sign the session ID. For this reason, the secret should
+contain at least 32 bytes of entropy.
+
+##### store
+
+The session store instance, defaults to a new `MemoryStore` instance.
+
+##### unset
+
+Control the result of unsetting `req.session` (through `delete`, setting to `null`,
+etc.).
+
+The default value is `'keep'`.
+
+ - `'destroy'` The session will be destroyed (deleted) when the response ends.
+ - `'keep'` The session in the store will be kept, but modifications made during
+ the request are ignored and not saved.
+
+### req.session
+
+To store or access session data, simply use the request property `req.session`,
+which is (generally) serialized as JSON by the store, so nested objects
+are typically fine. For example below is a user-specific view counter:
+
+```js
+// Use the session middleware
+app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
+
+// Access the session as req.session
+app.get('/', function(req, res, next) {
+ if (req.session.views) {
+ req.session.views++
+ res.setHeader('Content-Type', 'text/html')
+ res.write('views: ' + req.session.views + '
')
+ res.write('expires in: ' + (req.session.cookie.maxAge / 1000) + 's
')
+ res.end()
+ } else {
+ req.session.views = 1
+ res.end('welcome to the session demo. refresh!')
+ }
+})
+```
+
+#### Session.regenerate(callback)
+
+To regenerate the session simply invoke the method. Once complete,
+a new SID and `Session` instance will be initialized at `req.session`
+and the `callback` will be invoked.
+
+```js
+req.session.regenerate(function(err) {
+ // will have a new session here
+})
+```
+
+#### Session.destroy(callback)
+
+Destroys the session and will unset the `req.session` property.
+Once complete, the `callback` will be invoked.
+
+```js
+req.session.destroy(function(err) {
+ // cannot access session here
+})
+```
+
+#### Session.reload(callback)
+
+Reloads the session data from the store and re-populates the
+`req.session` object. Once complete, the `callback` will be invoked.
+
+```js
+req.session.reload(function(err) {
+ // session updated
+})
+```
+
+#### Session.save(callback)
+
+Save the session back to the store, replacing the contents on the store with the
+contents in memory (though a store may do something else--consult the store's
+documentation for exact behavior).
+
+This method is automatically called at the end of the HTTP response if the
+session data has been altered (though this behavior can be altered with various
+options in the middleware constructor). Because of this, typically this method
+does not need to be called.
+
+There are some cases where it is useful to call this method, for example,
+redirects, long-lived requests or in WebSockets.
+
+```js
+req.session.save(function(err) {
+ // session saved
+})
+```
+
+#### Session.touch()
+
+Updates the `.maxAge` property. Typically this is
+not necessary to call, as the session middleware does this for you.
+
+### req.session.id
+
+Each session has a unique ID associated with it. This property is an
+alias of [`req.sessionID`](#reqsessionid-1) and cannot be modified.
+It has been added to make the session ID accessible from the `session`
+object.
+
+### req.session.cookie
+
+Each session has a unique cookie object accompany it. This allows
+you to alter the session cookie per visitor. For example we can
+set `req.session.cookie.expires` to `false` to enable the cookie
+to remain for only the duration of the user-agent.
+
+#### Cookie.maxAge
+
+Alternatively `req.session.cookie.maxAge` will return the time
+remaining in milliseconds, which we may also re-assign a new value
+to adjust the `.expires` property appropriately. The following
+are essentially equivalent
+
+```js
+var hour = 3600000
+req.session.cookie.expires = new Date(Date.now() + hour)
+req.session.cookie.maxAge = hour
+```
+
+For example when `maxAge` is set to `60000` (one minute), and 30 seconds
+has elapsed it will return `30000` until the current request has completed,
+at which time `req.session.touch()` is called to reset
+`req.session.cookie.maxAge` to its original value.
+
+```js
+req.session.cookie.maxAge // => 30000
+```
+
+#### Cookie.originalMaxAge
+
+The `req.session.cookie.originalMaxAge` property returns the original
+`maxAge` (time-to-live), in milliseconds, of the session cookie.
+
+### req.sessionID
+
+To get the ID of the loaded session, access the request property
+`req.sessionID`. This is simply a read-only value set when a session
+is loaded/created.
+
+## Session Store Implementation
+
+Every session store _must_ be an `EventEmitter` and implement specific
+methods. The following methods are the list of **required**, **recommended**,
+and **optional**.
+
+ * Required methods are ones that this module will always call on the store.
+ * Recommended methods are ones that this module will call on the store if
+ available.
+ * Optional methods are ones this module does not call at all, but helps
+ present uniform stores to users.
+
+For an example implementation view the [connect-redis](http://github.com/visionmedia/connect-redis) repo.
+
+### store.all(callback)
+
+**Optional**
+
+This optional method is used to get all sessions in the store as an array. The
+`callback` should be called as `callback(error, sessions)`.
+
+### store.destroy(sid, callback)
+
+**Required**
+
+This required method is used to destroy/delete a session from the store given
+a session ID (`sid`). The `callback` should be called as `callback(error)` once
+the session is destroyed.
+
+### store.clear(callback)
+
+**Optional**
+
+This optional method is used to delete all sessions from the store. The
+`callback` should be called as `callback(error)` once the store is cleared.
+
+### store.length(callback)
+
+**Optional**
+
+This optional method is used to get the count of all sessions in the store.
+The `callback` should be called as `callback(error, len)`.
+
+### store.get(sid, callback)
+
+**Required**
+
+This required method is used to get a session from the store given a session
+ID (`sid`). The `callback` should be called as `callback(error, session)`.
+
+The `session` argument should be a session if found, otherwise `null` or
+`undefined` if the session was not found (and there was no error). A special
+case is made when `error.code === 'ENOENT'` to act like `callback(null, null)`.
+
+### store.set(sid, session, callback)
+
+**Required**
+
+This required method is used to upsert a session into the store given a
+session ID (`sid`) and session (`session`) object. The callback should be
+called as `callback(error)` once the session has been set in the store.
+
+### store.touch(sid, session, callback)
+
+**Recommended**
+
+This recommended method is used to "touch" a given session given a
+session ID (`sid`) and session (`session`) object. The `callback` should be
+called as `callback(error)` once the session has been touched.
+
+This is primarily used when the store will automatically delete idle sessions
+and this method is used to signal to the store the given session is active,
+potentially resetting the idle timer.
+
+## Compatible Session Stores
+
+The following modules implement a session store that is compatible with this
+module. Please make a PR to add additional modules :)
+
+[![â
][aerospike-session-store-image] aerospike-session-store][aerospike-session-store-url] A session store using [Aerospike](http://www.aerospike.com/).
+
+[aerospike-session-store-url]: https://www.npmjs.com/package/aerospike-session-store
+[aerospike-session-store-image]: https://badgen.net/github/stars/aerospike/aerospike-session-store-expressjs?label=%E2%98%85
+
+[![â
][better-sqlite3-session-store-image] better-sqlite3-session-store][better-sqlite3-session-store-url] A session store based on [better-sqlite3](https://github.com/JoshuaWise/better-sqlite3).
+
+[better-sqlite3-session-store-url]: https://www.npmjs.com/package/better-sqlite3-session-store
+[better-sqlite3-session-store-image]: https://badgen.net/github/stars/timdaub/better-sqlite3-session-store?label=%E2%98%85
+
+[![â
][cassandra-store-image] cassandra-store][cassandra-store-url] An Apache Cassandra-based session store.
+
+[cassandra-store-url]: https://www.npmjs.com/package/cassandra-store
+[cassandra-store-image]: https://badgen.net/github/stars/webcc/cassandra-store?label=%E2%98%85
+
+[![â
][cluster-store-image] cluster-store][cluster-store-url] A wrapper for using in-process / embedded
+stores - such as SQLite (via knex), leveldb, files, or memory - with node cluster (desirable for Raspberry Pi 2
+and other multi-core embedded devices).
+
+[cluster-store-url]: https://www.npmjs.com/package/cluster-store
+[cluster-store-image]: https://badgen.net/github/stars/coolaj86/cluster-store?label=%E2%98%85
+
+[![â
][connect-arango-image] connect-arango][connect-arango-url] An ArangoDB-based session store.
+
+[connect-arango-url]: https://www.npmjs.com/package/connect-arango
+[connect-arango-image]: https://badgen.net/github/stars/AlexanderArvidsson/connect-arango?label=%E2%98%85
+
+[![â
][connect-azuretables-image] connect-azuretables][connect-azuretables-url] An [Azure Table Storage](https://azure.microsoft.com/en-gb/services/storage/tables/)-based session store.
+
+[connect-azuretables-url]: https://www.npmjs.com/package/connect-azuretables
+[connect-azuretables-image]: https://badgen.net/github/stars/mike-goodwin/connect-azuretables?label=%E2%98%85
+
+[![â
][connect-cloudant-store-image] connect-cloudant-store][connect-cloudant-store-url] An [IBM Cloudant](https://cloudant.com/)-based session store.
+
+[connect-cloudant-store-url]: https://www.npmjs.com/package/connect-cloudant-store
+[connect-cloudant-store-image]: https://badgen.net/github/stars/adriantanasa/connect-cloudant-store?label=%E2%98%85
+
+[![â
][connect-cosmosdb-image] connect-cosmosdb][connect-cosmosdb-url] An Azure [Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db/)-based session store.
+
+[connect-cosmosdb-url]: https://www.npmjs.com/package/connect-cosmosdb
+[connect-cosmosdb-image]: https://badgen.net/github/stars/thekillingspree/connect-cosmosdb?label=%E2%98%85
+
+[![â
][connect-couchbase-image] connect-couchbase][connect-couchbase-url] A [couchbase](http://www.couchbase.com/)-based session store.
+
+[connect-couchbase-url]: https://www.npmjs.com/package/connect-couchbase
+[connect-couchbase-image]: https://badgen.net/github/stars/christophermina/connect-couchbase?label=%E2%98%85
+
+[![â
][connect-datacache-image] connect-datacache][connect-datacache-url] An [IBM Bluemix Data Cache](http://www.ibm.com/cloud-computing/bluemix/)-based session store.
+
+[connect-datacache-url]: https://www.npmjs.com/package/connect-datacache
+[connect-datacache-image]: https://badgen.net/github/stars/adriantanasa/connect-datacache?label=%E2%98%85
+
+[![â
][@google-cloud/connect-datastore-image] @google-cloud/connect-datastore][@google-cloud/connect-datastore-url] A [Google Cloud Datastore](https://cloud.google.com/datastore/docs/concepts/overview)-based session store.
+
+[@google-cloud/connect-datastore-url]: https://www.npmjs.com/package/@google-cloud/connect-datastore
+[@google-cloud/connect-datastore-image]: https://badgen.net/github/stars/GoogleCloudPlatform/cloud-datastore-session-node?label=%E2%98%85
+
+[![â
][connect-db2-image] connect-db2][connect-db2-url] An IBM DB2-based session store built using [ibm_db](https://www.npmjs.com/package/ibm_db) module.
+
+[connect-db2-url]: https://www.npmjs.com/package/connect-db2
+[connect-db2-image]: https://badgen.net/github/stars/wallali/connect-db2?label=%E2%98%85
+
+[![â
][connect-dynamodb-image] connect-dynamodb][connect-dynamodb-url] A DynamoDB-based session store.
+
+[connect-dynamodb-url]: https://www.npmjs.com/package/connect-dynamodb
+[connect-dynamodb-image]: https://badgen.net/github/stars/ca98am79/connect-dynamodb?label=%E2%98%85
+
+[![â
][@google-cloud/connect-firestore-image] @google-cloud/connect-firestore][@google-cloud/connect-firestore-url] A [Google Cloud Firestore](https://cloud.google.com/firestore/docs/overview)-based session store.
+
+[@google-cloud/connect-firestore-url]: https://www.npmjs.com/package/@google-cloud/connect-firestore
+[@google-cloud/connect-firestore-image]: https://badgen.net/github/stars/googleapis/nodejs-firestore-session?label=%E2%98%85
+
+[![â
][connect-hazelcast-image] connect-hazelcast][connect-hazelcast-url] Hazelcast session store for Connect and Express.
+
+[connect-hazelcast-url]: https://www.npmjs.com/package/connect-hazelcast
+[connect-hazelcast-image]: https://badgen.net/github/stars/huseyinbabal/connect-hazelcast?label=%E2%98%85
+
+[![â
][connect-loki-image] connect-loki][connect-loki-url] A Loki.js-based session store.
+
+[connect-loki-url]: https://www.npmjs.com/package/connect-loki
+[connect-loki-image]: https://badgen.net/github/stars/Requarks/connect-loki?label=%E2%98%85
+
+[![â
][connect-lowdb-image] connect-lowdb][connect-lowdb-url] A lowdb-based session store.
+
+[connect-lowdb-url]: https://www.npmjs.com/package/connect-lowdb
+[connect-lowdb-image]: https://badgen.net/github/stars/travishorn/connect-lowdb?label=%E2%98%85
+
+[![â
][connect-memcached-image] connect-memcached][connect-memcached-url] A memcached-based session store.
+
+[connect-memcached-url]: https://www.npmjs.com/package/connect-memcached
+[connect-memcached-image]: https://badgen.net/github/stars/balor/connect-memcached?label=%E2%98%85
+
+[![â
][connect-memjs-image] connect-memjs][connect-memjs-url] A memcached-based session store using
+[memjs](https://www.npmjs.com/package/memjs) as the memcached client.
+
+[connect-memjs-url]: https://www.npmjs.com/package/connect-memjs
+[connect-memjs-image]: https://badgen.net/github/stars/liamdon/connect-memjs?label=%E2%98%85
+
+[![â
][connect-ml-image] connect-ml][connect-ml-url] A MarkLogic Server-based session store.
+
+[connect-ml-url]: https://www.npmjs.com/package/connect-ml
+[connect-ml-image]: https://badgen.net/github/stars/bluetorch/connect-ml?label=%E2%98%85
+
+[![â
][connect-monetdb-image] connect-monetdb][connect-monetdb-url] A MonetDB-based session store.
+
+[connect-monetdb-url]: https://www.npmjs.com/package/connect-monetdb
+[connect-monetdb-image]: https://badgen.net/github/stars/MonetDB/npm-connect-monetdb?label=%E2%98%85
+
+[![â
][connect-mongo-image] connect-mongo][connect-mongo-url] A MongoDB-based session store.
+
+[connect-mongo-url]: https://www.npmjs.com/package/connect-mongo
+[connect-mongo-image]: https://badgen.net/github/stars/kcbanner/connect-mongo?label=%E2%98%85
+
+[![â
][connect-mongodb-session-image] connect-mongodb-session][connect-mongodb-session-url] Lightweight MongoDB-based session store built and maintained by MongoDB.
+
+[connect-mongodb-session-url]: https://www.npmjs.com/package/connect-mongodb-session
+[connect-mongodb-session-image]: https://badgen.net/github/stars/mongodb-js/connect-mongodb-session?label=%E2%98%85
+
+[![â
][connect-mssql-v2-image] connect-mssql-v2][connect-mssql-v2-url] A Microsoft SQL Server-based session store based on [connect-mssql](https://www.npmjs.com/package/connect-mssql).
+
+[connect-mssql-v2-url]: https://www.npmjs.com/package/connect-mssql-v2
+[connect-mssql-v2-image]: https://badgen.net/github/stars/jluboff/connect-mssql-v2?label=%E2%98%85
+
+[![â
][connect-neo4j-image] connect-neo4j][connect-neo4j-url] A [Neo4j](https://neo4j.com)-based session store.
+
+[connect-neo4j-url]: https://www.npmjs.com/package/connect-neo4j
+[connect-neo4j-image]: https://badgen.net/github/stars/MaxAndersson/connect-neo4j?label=%E2%98%85
+
+[![â
][connect-ottoman-image] connect-ottoman][connect-ottoman-url] A [couchbase ottoman](http://www.couchbase.com/)-based session store.
+
+[connect-ottoman-url]: https://www.npmjs.com/package/connect-ottoman
+[connect-ottoman-image]: https://badgen.net/github/stars/noiissyboy/connect-ottoman?label=%E2%98%85
+
+[![â
][connect-pg-simple-image] connect-pg-simple][connect-pg-simple-url] A PostgreSQL-based session store.
+
+[connect-pg-simple-url]: https://www.npmjs.com/package/connect-pg-simple
+[connect-pg-simple-image]: https://badgen.net/github/stars/voxpelli/node-connect-pg-simple?label=%E2%98%85
+
+[![â
][connect-redis-image] connect-redis][connect-redis-url] A Redis-based session store.
+
+[connect-redis-url]: https://www.npmjs.com/package/connect-redis
+[connect-redis-image]: https://badgen.net/github/stars/tj/connect-redis?label=%E2%98%85
+
+[![â
][connect-session-firebase-image] connect-session-firebase][connect-session-firebase-url] A session store based on the [Firebase Realtime Database](https://firebase.google.com/docs/database/)
+
+[connect-session-firebase-url]: https://www.npmjs.com/package/connect-session-firebase
+[connect-session-firebase-image]: https://badgen.net/github/stars/benweier/connect-session-firebase?label=%E2%98%85
+
+[![â
][connect-session-knex-image] connect-session-knex][connect-session-knex-url] A session store using
+[Knex.js](http://knexjs.org/), which is a SQL query builder for PostgreSQL, MySQL, MariaDB, SQLite3, and Oracle.
+
+[connect-session-knex-url]: https://www.npmjs.com/package/connect-session-knex
+[connect-session-knex-image]: https://badgen.net/github/stars/llambda/connect-session-knex?label=%E2%98%85
+
+[![â
][connect-session-sequelize-image] connect-session-sequelize][connect-session-sequelize-url] A session store using
+[Sequelize.js](http://sequelizejs.com/), which is a Node.js / io.js ORM for PostgreSQL, MySQL, SQLite and MSSQL.
+
+[connect-session-sequelize-url]: https://www.npmjs.com/package/connect-session-sequelize
+[connect-session-sequelize-image]: https://badgen.net/github/stars/mweibel/connect-session-sequelize?label=%E2%98%85
+
+[![â
][connect-sqlite3-image] connect-sqlite3][connect-sqlite3-url] A [SQLite3](https://github.com/mapbox/node-sqlite3) session store modeled after the TJ's `connect-redis` store.
+
+[connect-sqlite3-url]: https://www.npmjs.com/package/connect-sqlite3
+[connect-sqlite3-image]: https://badgen.net/github/stars/rawberg/connect-sqlite3?label=%E2%98%85
+
+[![â
][connect-typeorm-image] connect-typeorm][connect-typeorm-url] A [TypeORM](https://github.com/typeorm/typeorm)-based session store.
+
+[connect-typeorm-url]: https://www.npmjs.com/package/connect-typeorm
+[connect-typeorm-image]: https://badgen.net/github/stars/makepost/connect-typeorm?label=%E2%98%85
+
+[![â
][couchdb-expression-image] couchdb-expression][couchdb-expression-url] A [CouchDB](https://couchdb.apache.org/)-based session store.
+
+[couchdb-expression-url]: https://www.npmjs.com/package/couchdb-expression
+[couchdb-expression-image]: https://badgen.net/github/stars/tkshnwesper/couchdb-expression?label=%E2%98%85
+
+[![â
][dynamodb-store-image] dynamodb-store][dynamodb-store-url] A DynamoDB-based session store.
+
+[dynamodb-store-url]: https://www.npmjs.com/package/dynamodb-store
+[dynamodb-store-image]: https://badgen.net/github/stars/rafaelrpinto/dynamodb-store?label=%E2%98%85
+
+[![â
][dynamodb-store-v3-image] dynamodb-store-v3][dynamodb-store-v3-url] Implementation of a session store using DynamoDB backed by the [AWS SDK for JavaScript v3](https://github.com/aws/aws-sdk-js-v3).
+
+[dynamodb-store-v3-url]: https://www.npmjs.com/package/dynamodb-store-v3
+[dynamodb-store-v3-image]: https://badgen.net/github/stars/FryDay/dynamodb-store-v3?label=%E2%98%85
+
+[![â
][express-etcd-image] express-etcd][express-etcd-url] An [etcd](https://github.com/stianeikeland/node-etcd) based session store.
+
+[express-etcd-url]: https://www.npmjs.com/package/express-etcd
+[express-etcd-image]: https://badgen.net/github/stars/gildean/express-etcd?label=%E2%98%85
+
+[![â
][express-mysql-session-image] express-mysql-session][express-mysql-session-url] A session store using native
+[MySQL](https://www.mysql.com/) via the [node-mysql](https://github.com/felixge/node-mysql) module.
+
+[express-mysql-session-url]: https://www.npmjs.com/package/express-mysql-session
+[express-mysql-session-image]: https://badgen.net/github/stars/chill117/express-mysql-session?label=%E2%98%85
+
+[![â
][express-nedb-session-image] express-nedb-session][express-nedb-session-url] A NeDB-based session store.
+
+[express-nedb-session-url]: https://www.npmjs.com/package/express-nedb-session
+[express-nedb-session-image]: https://badgen.net/github/stars/louischatriot/express-nedb-session?label=%E2%98%85
+
+[![â
][express-oracle-session-image] express-oracle-session][express-oracle-session-url] A session store using native
+[oracle](https://www.oracle.com/) via the [node-oracledb](https://www.npmjs.com/package/oracledb) module.
+
+[express-oracle-session-url]: https://www.npmjs.com/package/express-oracle-session
+[express-oracle-session-image]: https://badgen.net/github/stars/slumber86/express-oracle-session?label=%E2%98%85
+
+[![â
][express-session-cache-manager-image] express-session-cache-manager][express-session-cache-manager-url]
+A store that implements [cache-manager](https://www.npmjs.com/package/cache-manager), which supports
+a [variety of storage types](https://www.npmjs.com/package/cache-manager#store-engines).
+
+[express-session-cache-manager-url]: https://www.npmjs.com/package/express-session-cache-manager
+[express-session-cache-manager-image]: https://badgen.net/github/stars/theogravity/express-session-cache-manager?label=%E2%98%85
+
+[![â
][express-session-etcd3-image] express-session-etcd3][express-session-etcd3-url] An [etcd3](https://github.com/mixer/etcd3) based session store.
+
+[express-session-etcd3-url]: https://www.npmjs.com/package/express-session-etcd3
+[express-session-etcd3-image]: https://badgen.net/github/stars/willgm/express-session-etcd3?label=%E2%98%85
+
+[![â
][express-session-level-image] express-session-level][express-session-level-url] A [LevelDB](https://github.com/Level/levelup) based session store.
+
+[express-session-level-url]: https://www.npmjs.com/package/express-session-level
+[express-session-level-image]: https://badgen.net/github/stars/tgohn/express-session-level?label=%E2%98%85
+
+[![â
][express-session-rsdb-image] express-session-rsdb][express-session-rsdb-url] Session store based on Rocket-Store: A very simple, super fast and yet powerful, flat file database.
+
+[express-session-rsdb-url]: https://www.npmjs.com/package/express-session-rsdb
+[express-session-rsdb-image]: https://badgen.net/github/stars/paragi/express-session-rsdb?label=%E2%98%85
+
+[![â
][express-sessions-image] express-sessions][express-sessions-url] A session store supporting both MongoDB and Redis.
+
+[express-sessions-url]: https://www.npmjs.com/package/express-sessions
+[express-sessions-image]: https://badgen.net/github/stars/konteck/express-sessions?label=%E2%98%85
+
+[![â
][firestore-store-image] firestore-store][firestore-store-url] A [Firestore](https://github.com/hendrysadrak/firestore-store)-based session store.
+
+[firestore-store-url]: https://www.npmjs.com/package/firestore-store
+[firestore-store-image]: https://badgen.net/github/stars/hendrysadrak/firestore-store?label=%E2%98%85
+
+[![â
][fortune-session-image] fortune-session][fortune-session-url] A [Fortune.js](https://github.com/fortunejs/fortune)
+based session store. Supports all backends supported by Fortune (MongoDB, Redis, Postgres, NeDB).
+
+[fortune-session-url]: https://www.npmjs.com/package/fortune-session
+[fortune-session-image]: https://badgen.net/github/stars/aliceklipper/fortune-session?label=%E2%98%85
+
+[![â
][hazelcast-store-image] hazelcast-store][hazelcast-store-url] A Hazelcast-based session store built on the [Hazelcast Node Client](https://www.npmjs.com/package/hazelcast-client).
+
+[hazelcast-store-url]: https://www.npmjs.com/package/hazelcast-store
+[hazelcast-store-image]: https://badgen.net/github/stars/jackspaniel/hazelcast-store?label=%E2%98%85
+
+[![â
][level-session-store-image] level-session-store][level-session-store-url] A LevelDB-based session store.
+
+[level-session-store-url]: https://www.npmjs.com/package/level-session-store
+[level-session-store-image]: https://badgen.net/github/stars/toddself/level-session-store?label=%E2%98%85
+
+[![â
][lowdb-session-store-image] lowdb-session-store][lowdb-session-store-url] A [lowdb](https://www.npmjs.com/package/lowdb)-based session store.
+
+[lowdb-session-store-url]: https://www.npmjs.com/package/lowdb-session-store
+[lowdb-session-store-image]: https://badgen.net/github/stars/fhellwig/lowdb-session-store?label=%E2%98%85
+
+[![â
][medea-session-store-image] medea-session-store][medea-session-store-url] A Medea-based session store.
+
+[medea-session-store-url]: https://www.npmjs.com/package/medea-session-store
+[medea-session-store-image]: https://badgen.net/github/stars/BenjaminVadant/medea-session-store?label=%E2%98%85
+
+[![â
][memorystore-image] memorystore][memorystore-url] A memory session store made for production.
+
+[memorystore-url]: https://www.npmjs.com/package/memorystore
+[memorystore-image]: https://badgen.net/github/stars/roccomuso/memorystore?label=%E2%98%85
+
+[![â
][mssql-session-store-image] mssql-session-store][mssql-session-store-url] A SQL Server-based session store.
+
+[mssql-session-store-url]: https://www.npmjs.com/package/mssql-session-store
+[mssql-session-store-image]: https://badgen.net/github/stars/jwathen/mssql-session-store?label=%E2%98%85
+
+[![â
][nedb-session-store-image] nedb-session-store][nedb-session-store-url] An alternate NeDB-based (either in-memory or file-persisted) session store.
+
+[nedb-session-store-url]: https://www.npmjs.com/package/nedb-session-store
+[nedb-session-store-image]: https://badgen.net/github/stars/JamesMGreene/nedb-session-store?label=%E2%98%85
+
+[![â
][@quixo3/prisma-session-store-image] @quixo3/prisma-session-store][@quixo3/prisma-session-store-url] A session store for the [Prisma Framework](https://www.prisma.io).
+
+[@quixo3/prisma-session-store-url]: https://www.npmjs.com/package/@quixo3/prisma-session-store
+[@quixo3/prisma-session-store-image]: https://badgen.net/github/stars/kleydon/prisma-session-store?label=%E2%98%85
+
+[![â
][restsession-image] restsession][restsession-url] Store sessions utilizing a RESTful API
+
+[restsession-url]: https://www.npmjs.com/package/restsession
+[restsession-image]: https://badgen.net/github/stars/jankal/restsession?label=%E2%98%85
+
+[![â
][sequelstore-connect-image] sequelstore-connect][sequelstore-connect-url] A session store using [Sequelize.js](http://sequelizejs.com/).
+
+[sequelstore-connect-url]: https://www.npmjs.com/package/sequelstore-connect
+[sequelstore-connect-image]: https://badgen.net/github/stars/MattMcFarland/sequelstore-connect?label=%E2%98%85
+
+[![â
][session-file-store-image] session-file-store][session-file-store-url] A file system-based session store.
+
+[session-file-store-url]: https://www.npmjs.com/package/session-file-store
+[session-file-store-image]: https://badgen.net/github/stars/valery-barysok/session-file-store?label=%E2%98%85
+
+[![â
][session-pouchdb-store-image] session-pouchdb-store][session-pouchdb-store-url] Session store for PouchDB / CouchDB. Accepts embedded, custom, or remote PouchDB instance and realtime synchronization.
+
+[session-pouchdb-store-url]: https://www.npmjs.com/package/session-pouchdb-store
+[session-pouchdb-store-image]: https://badgen.net/github/stars/solzimer/session-pouchdb-store?label=%E2%98%85
+
+[![â
][@cyclic.sh/session-store-image] @cyclic.sh/session-store][@cyclic.sh/session-store-url] A DynamoDB-based session store for [Cyclic.sh](https://www.cyclic.sh/) apps.
+
+[@cyclic.sh/session-store-url]: https://www.npmjs.com/package/@cyclic.sh/session-store
+[@cyclic.sh/session-store-image]: https://badgen.net/github/stars/cyclic-software/session-store?label=%E2%98%85
+
+[![â
][@databunker/session-store-image] @databunker/session-store][@databunker/session-store-url] A [Databunker](https://databunker.org/)-based encrypted session store.
+
+[@databunker/session-store-url]: https://www.npmjs.com/package/@databunker/session-store
+[@databunker/session-store-image]: https://badgen.net/github/stars/securitybunker/databunker-session-store?label=%E2%98%85
+
+[![â
][sessionstore-image] sessionstore][sessionstore-url] A session store that works with various databases.
+
+[sessionstore-url]: https://www.npmjs.com/package/sessionstore
+[sessionstore-image]: https://badgen.net/github/stars/adrai/sessionstore?label=%E2%98%85
+
+[![â
][tch-nedb-session-image] tch-nedb-session][tch-nedb-session-url] A file system session store based on NeDB.
+
+[tch-nedb-session-url]: https://www.npmjs.com/package/tch-nedb-session
+[tch-nedb-session-image]: https://badgen.net/github/stars/tomaschyly/NeDBSession?label=%E2%98%85
+
+## Examples
+
+### View counter
+
+A simple example using `express-session` to store page views for a user.
+
+```js
+var express = require('express')
+var parseurl = require('parseurl')
+var session = require('express-session')
+
+var app = express()
+
+app.use(session({
+ secret: 'keyboard cat',
+ resave: false,
+ saveUninitialized: true
+}))
+
+app.use(function (req, res, next) {
+ if (!req.session.views) {
+ req.session.views = {}
+ }
+
+ // get the url pathname
+ var pathname = parseurl(req).pathname
+
+ // count the views
+ req.session.views[pathname] = (req.session.views[pathname] || 0) + 1
+
+ next()
+})
+
+app.get('/foo', function (req, res, next) {
+ res.send('you viewed this page ' + req.session.views['/foo'] + ' times')
+})
+
+app.get('/bar', function (req, res, next) {
+ res.send('you viewed this page ' + req.session.views['/bar'] + ' times')
+})
+
+app.listen(3000)
+```
+
+### User login
+
+A simple example using `express-session` to keep a user log in session.
+
+```js
+var escapeHtml = require('escape-html')
+var express = require('express')
+var session = require('express-session')
+
+var app = express()
+
+app.use(session({
+ secret: 'keyboard cat',
+ resave: false,
+ saveUninitialized: true
+}))
+
+// middleware to test if authenticated
+function isAuthenticated (req, res, next) {
+ if (req.session.user) next()
+ else next('route')
+}
+
+app.get('/', isAuthenticated, function (req, res) {
+ // this is only called when there is an authentication user due to isAuthenticated
+ res.send('hello, ' + escapeHtml(req.session.user) + '!' +
+ ' Logout')
+})
+
+app.get('/', function (req, res) {
+ res.send('')
+})
+
+app.post('/login', express.urlencoded({ extended: false }), function (req, res) {
+ // login logic to validate req.body.user and req.body.pass
+ // would be implemented here. for this example any combo works
+
+ // regenerate the session, which is good practice to help
+ // guard against forms of session fixation
+ req.session.regenerate(function (err) {
+ if (err) next(err)
+
+ // store user information in session, typically a user id
+ req.session.user = req.body.user
+
+ // save the session before redirection to ensure page
+ // load does not happen before session is saved
+ req.session.save(function (err) {
+ if (err) return next(err)
+ res.redirect('/')
+ })
+ })
+})
+
+app.get('/logout', function (req, res, next) {
+ // logout logic
+
+ // clear the user from the session object and save.
+ // this will ensure that re-using the old session id
+ // does not have a logged in user
+ req.session.user = null
+ req.session.save(function (err) {
+ if (err) next(err)
+
+ // regenerate the session, which is good practice to help
+ // guard against forms of session fixation
+ req.session.regenerate(function (err) {
+ if (err) next(err)
+ res.redirect('/')
+ })
+ })
+})
+
+app.listen(3000)
+```
+
+## Debugging
+
+This module uses the [debug](https://www.npmjs.com/package/debug) module
+internally to log information about session operations.
+
+To see all the internal logs, set the `DEBUG` environment variable to
+`express-session` when launching your app (`npm start`, in this example):
+
+```sh
+$ DEBUG=express-session npm start
+```
+
+On Windows, use the corresponding command;
+
+```sh
+> set DEBUG=express-session & npm start
+```
+
+## License
+
+[MIT](LICENSE)
+
+[rfc-6265bis-03-4.1.2.7]: https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-4.1.2.7
+[rfc-cutler-httpbis-partitioned-cookies]: https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/
+[rfc-west-cookie-priority-00-4.1]: https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1
+[ci-image]: https://badgen.net/github/checks/expressjs/session/master?label=ci
+[ci-url]: https://github.com/expressjs/session/actions?query=workflow%3Aci
+[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/session/master
+[coveralls-url]: https://coveralls.io/r/expressjs/session?branch=master
+[node-url]: https://nodejs.org/en/download
+[npm-downloads-image]: https://badgen.net/npm/dm/express-session
+[npm-url]: https://npmjs.org/package/express-session
+[npm-version-image]: https://badgen.net/npm/v/express-session
diff --git a/node_modules/express-session/index.js b/node_modules/express-session/index.js
new file mode 100644
index 00000000..d41b2378
--- /dev/null
+++ b/node_modules/express-session/index.js
@@ -0,0 +1,693 @@
+/*!
+ * express-session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2014-2015 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var Buffer = require('safe-buffer').Buffer
+var cookie = require('cookie');
+var crypto = require('crypto')
+var debug = require('debug')('express-session');
+var deprecate = require('depd')('express-session');
+var onHeaders = require('on-headers')
+var parseUrl = require('parseurl');
+var signature = require('cookie-signature')
+var uid = require('uid-safe').sync
+
+var Cookie = require('./session/cookie')
+var MemoryStore = require('./session/memory')
+var Session = require('./session/session')
+var Store = require('./session/store')
+
+// environment
+
+var env = process.env.NODE_ENV;
+
+/**
+ * Expose the middleware.
+ */
+
+exports = module.exports = session;
+
+/**
+ * Expose constructors.
+ */
+
+exports.Store = Store;
+exports.Cookie = Cookie;
+exports.Session = Session;
+exports.MemoryStore = MemoryStore;
+
+/**
+ * Warning message for `MemoryStore` usage in production.
+ * @private
+ */
+
+var warning = 'Warning: connect.session() MemoryStore is not\n'
+ + 'designed for a production environment, as it will leak\n'
+ + 'memory, and will not scale past a single process.';
+
+/**
+ * Node.js 0.8+ async implementation.
+ * @private
+ */
+
+/* istanbul ignore next */
+var defer = typeof setImmediate === 'function'
+ ? setImmediate
+ : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
+
+/**
+ * Setup session store with the given `options`.
+ *
+ * @param {Object} [options]
+ * @param {Object} [options.cookie] Options for cookie
+ * @param {Function} [options.genid]
+ * @param {String} [options.name=connect.sid] Session ID cookie name
+ * @param {Boolean} [options.proxy]
+ * @param {Boolean} [options.resave] Resave unmodified sessions back to the store
+ * @param {Boolean} [options.rolling] Enable/disable rolling session expiration
+ * @param {Boolean} [options.saveUninitialized] Save uninitialized sessions to the store
+ * @param {String|Array} [options.secret] Secret for signing session ID
+ * @param {Object} [options.store=MemoryStore] Session store
+ * @param {String} [options.unset]
+ * @return {Function} middleware
+ * @public
+ */
+
+function session(options) {
+ var opts = options || {}
+
+ // get the cookie options
+ var cookieOptions = opts.cookie || {}
+
+ // get the session id generate function
+ var generateId = opts.genid || generateSessionId
+
+ // get the session cookie name
+ var name = opts.name || opts.key || 'connect.sid'
+
+ // get the session store
+ var store = opts.store || new MemoryStore()
+
+ // get the trust proxy setting
+ var trustProxy = opts.proxy
+
+ // get the resave session option
+ var resaveSession = opts.resave;
+
+ // get the rolling session option
+ var rollingSessions = Boolean(opts.rolling)
+
+ // get the save uninitialized session option
+ var saveUninitializedSession = opts.saveUninitialized
+
+ // get the cookie signing secret
+ var secret = opts.secret
+
+ if (typeof generateId !== 'function') {
+ throw new TypeError('genid option must be a function');
+ }
+
+ if (resaveSession === undefined) {
+ deprecate('undefined resave option; provide resave option');
+ resaveSession = true;
+ }
+
+ if (saveUninitializedSession === undefined) {
+ deprecate('undefined saveUninitialized option; provide saveUninitialized option');
+ saveUninitializedSession = true;
+ }
+
+ if (opts.unset && opts.unset !== 'destroy' && opts.unset !== 'keep') {
+ throw new TypeError('unset option must be "destroy" or "keep"');
+ }
+
+ // TODO: switch to "destroy" on next major
+ var unsetDestroy = opts.unset === 'destroy'
+
+ if (Array.isArray(secret) && secret.length === 0) {
+ throw new TypeError('secret option array must contain one or more strings');
+ }
+
+ if (secret && !Array.isArray(secret)) {
+ secret = [secret];
+ }
+
+ if (!secret) {
+ deprecate('req.secret; provide secret option');
+ }
+
+ // notify user that this store is not
+ // meant for a production environment
+ /* istanbul ignore next: not tested */
+ if (env === 'production' && store instanceof MemoryStore) {
+ console.warn(warning);
+ }
+
+ // generates the new session
+ store.generate = function(req){
+ req.sessionID = generateId(req);
+ req.session = new Session(req);
+ req.session.cookie = new Cookie(cookieOptions);
+
+ if (cookieOptions.secure === 'auto') {
+ req.session.cookie.secure = issecure(req, trustProxy);
+ }
+ };
+
+ var storeImplementsTouch = typeof store.touch === 'function';
+
+ // register event listeners for the store to track readiness
+ var storeReady = true
+ store.on('disconnect', function ondisconnect() {
+ storeReady = false
+ })
+ store.on('connect', function onconnect() {
+ storeReady = true
+ })
+
+ return function session(req, res, next) {
+ // self-awareness
+ if (req.session) {
+ next()
+ return
+ }
+
+ // Handle connection as if there is no session if
+ // the store has temporarily disconnected etc
+ if (!storeReady) {
+ debug('store is disconnected')
+ next()
+ return
+ }
+
+ // pathname mismatch
+ var originalPath = parseUrl.original(req).pathname || '/'
+ if (originalPath.indexOf(cookieOptions.path || '/') !== 0) {
+ debug('pathname mismatch')
+ next()
+ return
+ }
+
+ // ensure a secret is available or bail
+ if (!secret && !req.secret) {
+ next(new Error('secret option required for sessions'));
+ return;
+ }
+
+ // backwards compatibility for signed cookies
+ // req.secret is passed from the cookie parser middleware
+ var secrets = secret || [req.secret];
+
+ var originalHash;
+ var originalId;
+ var savedHash;
+ var touched = false
+
+ // expose store
+ req.sessionStore = store;
+
+ // get the session ID from the cookie
+ var cookieId = req.sessionID = getcookie(req, name, secrets);
+
+ // set-cookie
+ onHeaders(res, function(){
+ if (!req.session) {
+ debug('no session');
+ return;
+ }
+
+ if (!shouldSetCookie(req)) {
+ return;
+ }
+
+ // only send secure cookies via https
+ if (req.session.cookie.secure && !issecure(req, trustProxy)) {
+ debug('not secured');
+ return;
+ }
+
+ if (!touched) {
+ // touch session
+ req.session.touch()
+ touched = true
+ }
+
+ // set cookie
+ try {
+ setcookie(res, name, req.sessionID, secrets[0], req.session.cookie.data)
+ } catch (err) {
+ defer(next, err)
+ }
+ });
+
+ // proxy end() to commit the session
+ var _end = res.end;
+ var _write = res.write;
+ var ended = false;
+ res.end = function end(chunk, encoding) {
+ if (ended) {
+ return false;
+ }
+
+ ended = true;
+
+ var ret;
+ var sync = true;
+
+ function writeend() {
+ if (sync) {
+ ret = _end.call(res, chunk, encoding);
+ sync = false;
+ return;
+ }
+
+ _end.call(res);
+ }
+
+ function writetop() {
+ if (!sync) {
+ return ret;
+ }
+
+ if (!res._header) {
+ res._implicitHeader()
+ }
+
+ if (chunk == null) {
+ ret = true;
+ return ret;
+ }
+
+ var contentLength = Number(res.getHeader('Content-Length'));
+
+ if (!isNaN(contentLength) && contentLength > 0) {
+ // measure chunk
+ chunk = !Buffer.isBuffer(chunk)
+ ? Buffer.from(chunk, encoding)
+ : chunk;
+ encoding = undefined;
+
+ if (chunk.length !== 0) {
+ debug('split response');
+ ret = _write.call(res, chunk.slice(0, chunk.length - 1));
+ chunk = chunk.slice(chunk.length - 1, chunk.length);
+ return ret;
+ }
+ }
+
+ ret = _write.call(res, chunk, encoding);
+ sync = false;
+
+ return ret;
+ }
+
+ if (shouldDestroy(req)) {
+ // destroy session
+ debug('destroying');
+ store.destroy(req.sessionID, function ondestroy(err) {
+ if (err) {
+ defer(next, err);
+ }
+
+ debug('destroyed');
+ writeend();
+ });
+
+ return writetop();
+ }
+
+ // no session to save
+ if (!req.session) {
+ debug('no session');
+ return _end.call(res, chunk, encoding);
+ }
+
+ if (!touched) {
+ // touch session
+ req.session.touch()
+ touched = true
+ }
+
+ if (shouldSave(req)) {
+ req.session.save(function onsave(err) {
+ if (err) {
+ defer(next, err);
+ }
+
+ writeend();
+ });
+
+ return writetop();
+ } else if (storeImplementsTouch && shouldTouch(req)) {
+ // store implements touch method
+ debug('touching');
+ store.touch(req.sessionID, req.session, function ontouch(err) {
+ if (err) {
+ defer(next, err);
+ }
+
+ debug('touched');
+ writeend();
+ });
+
+ return writetop();
+ }
+
+ return _end.call(res, chunk, encoding);
+ };
+
+ // generate the session
+ function generate() {
+ store.generate(req);
+ originalId = req.sessionID;
+ originalHash = hash(req.session);
+ wrapmethods(req.session);
+ }
+
+ // inflate the session
+ function inflate (req, sess) {
+ store.createSession(req, sess)
+ originalId = req.sessionID
+ originalHash = hash(sess)
+
+ if (!resaveSession) {
+ savedHash = originalHash
+ }
+
+ wrapmethods(req.session)
+ }
+
+ function rewrapmethods (sess, callback) {
+ return function () {
+ if (req.session !== sess) {
+ wrapmethods(req.session)
+ }
+
+ callback.apply(this, arguments)
+ }
+ }
+
+ // wrap session methods
+ function wrapmethods(sess) {
+ var _reload = sess.reload
+ var _save = sess.save;
+
+ function reload(callback) {
+ debug('reloading %s', this.id)
+ _reload.call(this, rewrapmethods(this, callback))
+ }
+
+ function save() {
+ debug('saving %s', this.id);
+ savedHash = hash(this);
+ _save.apply(this, arguments);
+ }
+
+ Object.defineProperty(sess, 'reload', {
+ configurable: true,
+ enumerable: false,
+ value: reload,
+ writable: true
+ })
+
+ Object.defineProperty(sess, 'save', {
+ configurable: true,
+ enumerable: false,
+ value: save,
+ writable: true
+ });
+ }
+
+ // check if session has been modified
+ function isModified(sess) {
+ return originalId !== sess.id || originalHash !== hash(sess);
+ }
+
+ // check if session has been saved
+ function isSaved(sess) {
+ return originalId === sess.id && savedHash === hash(sess);
+ }
+
+ // determine if session should be destroyed
+ function shouldDestroy(req) {
+ return req.sessionID && unsetDestroy && req.session == null;
+ }
+
+ // determine if session should be saved to store
+ function shouldSave(req) {
+ // cannot set cookie without a session ID
+ if (typeof req.sessionID !== 'string') {
+ debug('session ignored because of bogus req.sessionID %o', req.sessionID);
+ return false;
+ }
+
+ return !saveUninitializedSession && !savedHash && cookieId !== req.sessionID
+ ? isModified(req.session)
+ : !isSaved(req.session)
+ }
+
+ // determine if session should be touched
+ function shouldTouch(req) {
+ // cannot set cookie without a session ID
+ if (typeof req.sessionID !== 'string') {
+ debug('session ignored because of bogus req.sessionID %o', req.sessionID);
+ return false;
+ }
+
+ return cookieId === req.sessionID && !shouldSave(req);
+ }
+
+ // determine if cookie should be set on response
+ function shouldSetCookie(req) {
+ // cannot set cookie without a session ID
+ if (typeof req.sessionID !== 'string') {
+ return false;
+ }
+
+ return cookieId !== req.sessionID
+ ? saveUninitializedSession || isModified(req.session)
+ : rollingSessions || req.session.cookie.expires != null && isModified(req.session);
+ }
+
+ // generate a session if the browser doesn't send a sessionID
+ if (!req.sessionID) {
+ debug('no SID sent, generating session');
+ generate();
+ next();
+ return;
+ }
+
+ // generate the session object
+ debug('fetching %s', req.sessionID);
+ store.get(req.sessionID, function(err, sess){
+ // error handling
+ if (err && err.code !== 'ENOENT') {
+ debug('error %j', err);
+ next(err)
+ return
+ }
+
+ try {
+ if (err || !sess) {
+ debug('no session found')
+ generate()
+ } else {
+ debug('session found')
+ inflate(req, sess)
+ }
+ } catch (e) {
+ next(e)
+ return
+ }
+
+ next()
+ });
+ };
+};
+
+/**
+ * Generate a session ID for a new session.
+ *
+ * @return {String}
+ * @private
+ */
+
+function generateSessionId(sess) {
+ return uid(24);
+}
+
+/**
+ * Get the session ID cookie from request.
+ *
+ * @return {string}
+ * @private
+ */
+
+function getcookie(req, name, secrets) {
+ var header = req.headers.cookie;
+ var raw;
+ var val;
+
+ // read from cookie header
+ if (header) {
+ var cookies = cookie.parse(header);
+
+ raw = cookies[name];
+
+ if (raw) {
+ if (raw.substr(0, 2) === 's:') {
+ val = unsigncookie(raw.slice(2), secrets);
+
+ if (val === false) {
+ debug('cookie signature invalid');
+ val = undefined;
+ }
+ } else {
+ debug('cookie unsigned')
+ }
+ }
+ }
+
+ // back-compat read from cookieParser() signedCookies data
+ if (!val && req.signedCookies) {
+ val = req.signedCookies[name];
+
+ if (val) {
+ deprecate('cookie should be available in req.headers.cookie');
+ }
+ }
+
+ // back-compat read from cookieParser() cookies data
+ if (!val && req.cookies) {
+ raw = req.cookies[name];
+
+ if (raw) {
+ if (raw.substr(0, 2) === 's:') {
+ val = unsigncookie(raw.slice(2), secrets);
+
+ if (val) {
+ deprecate('cookie should be available in req.headers.cookie');
+ }
+
+ if (val === false) {
+ debug('cookie signature invalid');
+ val = undefined;
+ }
+ } else {
+ debug('cookie unsigned')
+ }
+ }
+ }
+
+ return val;
+}
+
+/**
+ * Hash the given `sess` object omitting changes to `.cookie`.
+ *
+ * @param {Object} sess
+ * @return {String}
+ * @private
+ */
+
+function hash(sess) {
+ // serialize
+ var str = JSON.stringify(sess, function (key, val) {
+ // ignore sess.cookie property
+ if (this === sess && key === 'cookie') {
+ return
+ }
+
+ return val
+ })
+
+ // hash
+ return crypto
+ .createHash('sha1')
+ .update(str, 'utf8')
+ .digest('hex')
+}
+
+/**
+ * Determine if request is secure.
+ *
+ * @param {Object} req
+ * @param {Boolean} [trustProxy]
+ * @return {Boolean}
+ * @private
+ */
+
+function issecure(req, trustProxy) {
+ // socket is https server
+ if (req.connection && req.connection.encrypted) {
+ return true;
+ }
+
+ // do not trust proxy
+ if (trustProxy === false) {
+ return false;
+ }
+
+ // no explicit trust; try req.secure from express
+ if (trustProxy !== true) {
+ return req.secure === true
+ }
+
+ // read the proto from x-forwarded-proto header
+ var header = req.headers['x-forwarded-proto'] || '';
+ var index = header.indexOf(',');
+ var proto = index !== -1
+ ? header.substr(0, index).toLowerCase().trim()
+ : header.toLowerCase().trim()
+
+ return proto === 'https';
+}
+
+/**
+ * Set cookie on response.
+ *
+ * @private
+ */
+
+function setcookie(res, name, val, secret, options) {
+ var signed = 's:' + signature.sign(val, secret);
+ var data = cookie.serialize(name, signed, options);
+
+ debug('set-cookie %s', data);
+
+ var prev = res.getHeader('Set-Cookie') || []
+ var header = Array.isArray(prev) ? prev.concat(data) : [prev, data];
+
+ res.setHeader('Set-Cookie', header)
+}
+
+/**
+ * Verify and decode the given `val` with `secrets`.
+ *
+ * @param {String} val
+ * @param {Array} secrets
+ * @returns {String|Boolean}
+ * @private
+ */
+function unsigncookie(val, secrets) {
+ for (var i = 0; i < secrets.length; i++) {
+ var result = signature.unsign(val, secrets[i]);
+
+ if (result !== false) {
+ return result;
+ }
+ }
+
+ return false;
+}
diff --git a/node_modules/express-session/node_modules/cookie-signature/History.md b/node_modules/express-session/node_modules/cookie-signature/History.md
new file mode 100644
index 00000000..bcf8cc95
--- /dev/null
+++ b/node_modules/express-session/node_modules/cookie-signature/History.md
@@ -0,0 +1,42 @@
+1.0.7 / 2023-04-12
+==================
+
+* backport the buffer support from the 1.2.x release branch (thanks @FadhiliNjagi!)
+
+1.0.6 / 2015-02-03
+==================
+
+* use `npm test` instead of `make test` to run tests
+* clearer assertion messages when checking input
+
+1.0.5 / 2014-09-05
+==================
+
+* add license to package.json
+
+1.0.4 / 2014-06-25
+==================
+
+ * corrected avoidance of timing attacks (thanks @tenbits!)
+
+1.0.3 / 2014-01-28
+==================
+
+ * [incorrect] fix for timing attacks
+
+1.0.2 / 2014-01-28
+==================
+
+ * fix missing repository warning
+ * fix typo in test
+
+1.0.1 / 2013-04-15
+==================
+
+ * Revert "Changed underlying HMAC algo. to sha512."
+ * Revert "Fix for timing attacks on MAC verification."
+
+0.0.1 / 2010-01-03
+==================
+
+ * Initial release
diff --git a/node_modules/express-session/node_modules/cookie-signature/Readme.md b/node_modules/express-session/node_modules/cookie-signature/Readme.md
new file mode 100644
index 00000000..2559e841
--- /dev/null
+++ b/node_modules/express-session/node_modules/cookie-signature/Readme.md
@@ -0,0 +1,42 @@
+
+# cookie-signature
+
+ Sign and unsign cookies.
+
+## Example
+
+```js
+var cookie = require('cookie-signature');
+
+var val = cookie.sign('hello', 'tobiiscool');
+val.should.equal('hello.DGDUkGlIkCzPz+C0B064FNgHdEjox7ch8tOBGslZ5QI');
+
+var val = cookie.sign('hello', 'tobiiscool');
+cookie.unsign(val, 'tobiiscool').should.equal('hello');
+cookie.unsign(val, 'luna').should.be.false;
+```
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2012 LearnBoost <tj@learnboost.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.
\ No newline at end of file
diff --git a/node_modules/express-session/node_modules/cookie-signature/index.js b/node_modules/express-session/node_modules/cookie-signature/index.js
new file mode 100644
index 00000000..336d487f
--- /dev/null
+++ b/node_modules/express-session/node_modules/cookie-signature/index.js
@@ -0,0 +1,51 @@
+/**
+ * Module dependencies.
+ */
+
+var crypto = require('crypto');
+
+/**
+ * Sign the given `val` with `secret`.
+ *
+ * @param {String} val
+ * @param {String|NodeJS.ArrayBufferView|crypto.KeyObject} secret
+ * @return {String}
+ * @api private
+ */
+
+exports.sign = function(val, secret){
+ if ('string' !== typeof val) throw new TypeError("Cookie value must be provided as a string.");
+ if (null == secret) throw new TypeError("Secret key must be provided.");
+ return val + '.' + crypto
+ .createHmac('sha256', secret)
+ .update(val)
+ .digest('base64')
+ .replace(/\=+$/, '');
+};
+
+/**
+ * Unsign and decode the given `val` with `secret`,
+ * returning `false` if the signature is invalid.
+ *
+ * @param {String} val
+ * @param {String|NodeJS.ArrayBufferView|crypto.KeyObject} secret
+ * @return {String|Boolean}
+ * @api private
+ */
+
+exports.unsign = function(val, secret){
+ if ('string' !== typeof val) throw new TypeError("Signed cookie string must be provided.");
+ if (null == secret) throw new TypeError("Secret key must be provided.");
+ var str = val.slice(0, val.lastIndexOf('.'))
+ , mac = exports.sign(str, secret);
+
+ return sha1(mac) == sha1(val) ? str : false;
+};
+
+/**
+ * Private
+ */
+
+function sha1(str){
+ return crypto.createHash('sha1').update(str).digest('hex');
+}
diff --git a/node_modules/express-session/node_modules/cookie-signature/package.json b/node_modules/express-session/node_modules/cookie-signature/package.json
new file mode 100644
index 00000000..738487b5
--- /dev/null
+++ b/node_modules/express-session/node_modules/cookie-signature/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "cookie-signature",
+ "version": "1.0.7",
+ "description": "Sign and unsign cookies",
+ "keywords": ["cookie", "sign", "unsign"],
+ "author": "TJ Holowaychuk ",
+ "license": "MIT",
+ "repository": { "type": "git", "url": "https://github.com/visionmedia/node-cookie-signature.git"},
+ "dependencies": {},
+ "devDependencies": {
+ "mocha": "*",
+ "should": "*"
+ },
+ "scripts": {
+ "test": "mocha --require should --reporter spec"
+ },
+ "main": "index"
+}
\ No newline at end of file
diff --git a/node_modules/express-session/node_modules/debug/.coveralls.yml b/node_modules/express-session/node_modules/debug/.coveralls.yml
new file mode 100644
index 00000000..20a70685
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/node_modules/express-session/node_modules/debug/.eslintrc b/node_modules/express-session/node_modules/debug/.eslintrc
new file mode 100644
index 00000000..8a37ae2c
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/.eslintrc
@@ -0,0 +1,11 @@
+{
+ "env": {
+ "browser": true,
+ "node": true
+ },
+ "rules": {
+ "no-console": 0,
+ "no-empty": [1, { "allowEmptyCatch": true }]
+ },
+ "extends": "eslint:recommended"
+}
diff --git a/node_modules/express-session/node_modules/debug/.npmignore b/node_modules/express-session/node_modules/debug/.npmignore
new file mode 100644
index 00000000..5f60eecc
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/.npmignore
@@ -0,0 +1,9 @@
+support
+test
+examples
+example
+*.sock
+dist
+yarn.lock
+coverage
+bower.json
diff --git a/node_modules/express-session/node_modules/debug/.travis.yml b/node_modules/express-session/node_modules/debug/.travis.yml
new file mode 100644
index 00000000..6c6090c3
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/.travis.yml
@@ -0,0 +1,14 @@
+
+language: node_js
+node_js:
+ - "6"
+ - "5"
+ - "4"
+
+install:
+ - make node_modules
+
+script:
+ - make lint
+ - make test
+ - make coveralls
diff --git a/node_modules/express-session/node_modules/debug/CHANGELOG.md b/node_modules/express-session/node_modules/debug/CHANGELOG.md
new file mode 100644
index 00000000..eadaa189
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,362 @@
+
+2.6.9 / 2017-09-22
+==================
+
+ * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+ * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+ * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+ * Fix: Inline extend function in node implementation (#452, @dougwilson)
+ * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+
+ * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+ * Misc: clean up browser reference checks (#447, @thebigredgeek)
+ * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+ * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+ * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+ * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+ * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+ * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+ * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+ * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+ * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+ * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+ * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+ * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+ * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+ * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+ * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+ * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+ * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+ * Docs: fixed README typo (#391, @lurch)
+ * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+ * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+ * Fix: wrong reference in bower file (@thebigredgeek)
+ * Fix: webworker compatibility (@thebigredgeek)
+ * Fix: output formatting issue (#388, @kribblo)
+ * Fix: babel-loader compatibility (#383, @escwald)
+ * Misc: removed built asset from repo and publications (@thebigredgeek)
+ * Misc: moved source files to /src (#378, @yamikuronue)
+ * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+ * Test: coveralls integration (#378, @yamikuronue)
+ * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+ * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+ * Fix: custom log function (#379, @hsiliev)
+ * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+ * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+ * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+ * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+ * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+ * Fix: browser colors (#367, @tootallnate)
+ * Misc: travis ci integration (@thebigredgeek)
+ * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+ * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+ * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+ * Fix: revert "handle regex special characters" (@tootallnate)
+ * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+ * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+ * Improvement: allow colors in workers (#335, @botverse)
+ * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+ * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+ * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+ * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+ * Fix: be super-safe in index.js as well (@TooTallNate)
+ * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+ * Fix: Added electron compatibility (#324, @paulcbetts)
+ * Improvement: Added performance optimizations (@tootallnate)
+ * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+ * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+ * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+ * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+ * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+ * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+ * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+ * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+ * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+ * Readme: fix USE_COLORS to DEBUG_COLORS
+ * Readme: Doc fixes for format string sugar (#269, @mlucool)
+ * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+ * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+ * Readme: better docs for browser support (#224, @matthewmueller)
+ * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+ * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+ * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+ * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+ * package: update "ms" to v0.7.1 (#202, @dougwilson)
+ * README: add logging to file example (#193, @DanielOchoa)
+ * README: fixed a typo (#191, @amir-s)
+ * browser: expose `storage` (#190, @stephenmathieson)
+ * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+ * Updated stdout/stderr example (#186)
+ * Updated example/stdout.js to match debug current behaviour
+ * Renamed example/stderr.js to stdout.js
+ * Update Readme.md (#184)
+ * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+ * dist: recompile
+ * update "ms" to v0.7.0
+ * package: update "browserify" to v9.0.3
+ * component: fix "ms.js" repo location
+ * changed bower package name
+ * updated documentation about using debug in a browser
+ * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+ * browser: use `typeof` to check for `console` existence
+ * browser: check for `console.log` truthiness (fix IE 8/9)
+ * browser: add support for Chrome apps
+ * Readme: added Windows usage remarks
+ * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+ * node: implement `DEBUG_FD` env variable support
+ * package: update "browserify" to v6.1.0
+ * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+ * package: update "browserify" to v5.11.0
+ * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+ * dist: recompile
+ * example: remove `console.info()` log usage
+ * example: add "Content-Type" UTF-8 header to browser example
+ * browser: place %c marker after the space character
+ * browser: reset the "content" color via `color: inherit`
+ * browser: add colors support for Firefox >= v31
+ * debug: prefer an instance `log()` function over the global one (#119)
+ * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+ * Add support for multiple wildcards in namespaces (#122, @seegno)
+ * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+ * browser: update color palette (#113, @gscottolson)
+ * common: make console logging function configurable (#108, @timoxley)
+ * node: fix %o colors on old node <= 0.8.x
+ * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+ * browser: use `removeItem()` to clear localStorage
+ * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+ * package: add "contributors" section
+ * node: fix comment typo
+ * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+ * make ms diff be global, not be scope
+ * debug: ignore empty strings in enable()
+ * node: make DEBUG_COLORS able to disable coloring
+ * *: export the `colors` array
+ * npmignore: don't publish the `dist` dir
+ * Makefile: refactor to use browserify
+ * package: add "browserify" as a dev dependency
+ * Readme: add Web Inspector Colors section
+ * node: reset terminal color for the debug content
+ * node: map "%o" to `util.inspect()`
+ * browser: map "%j" to `JSON.stringify()`
+ * debug: add custom "formatters"
+ * debug: use "ms" module for humanizing the diff
+ * Readme: add "bash" syntax highlighting
+ * browser: add Firebug color support
+ * browser: add colors for WebKit browsers
+ * node: apply log to `console`
+ * rewrite: abstract common logic for Node & browsers
+ * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+ * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+ * add `enable()` method for nodejs. Closes #27
+ * change from stderr to stdout
+ * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+ * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+ * fix: catch localStorage security error when cookies are blocked (Chrome)
+ * add debug(err) support. Closes #46
+ * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+ * fix package.json
+ * fix: Mobile Safari (private mode) is broken with debug
+ * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+ * add repository URL to package.json
+ * add DEBUG_COLORED to force colored output
+ * add browserify support
+ * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+ * Added .component to package.json
+ * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+ * Added support for "-" prefix in DEBUG [Vinay Pulim]
+ * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+ * Added: humanize diffs. Closes #8
+ * Added `debug.disable()` to the CS variant
+ * Removed padding. Closes #10
+ * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+ * Added browser variant support for older browsers [TooTallNate]
+ * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+ * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+ * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+ * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+ * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+ * Initial release
diff --git a/node_modules/express-session/node_modules/debug/LICENSE b/node_modules/express-session/node_modules/debug/LICENSE
new file mode 100644
index 00000000..658c933d
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/LICENSE
@@ -0,0 +1,19 @@
+(The MIT License)
+
+Copyright (c) 2014 TJ Holowaychuk
+
+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/express-session/node_modules/debug/Makefile b/node_modules/express-session/node_modules/debug/Makefile
new file mode 100644
index 00000000..584da8bf
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/Makefile
@@ -0,0 +1,50 @@
+# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
+THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
+
+# BIN directory
+BIN := $(THIS_DIR)/node_modules/.bin
+
+# Path
+PATH := node_modules/.bin:$(PATH)
+SHELL := /bin/bash
+
+# applications
+NODE ?= $(shell which node)
+YARN ?= $(shell which yarn)
+PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
+BROWSERIFY ?= $(NODE) $(BIN)/browserify
+
+.FORCE:
+
+install: node_modules
+
+node_modules: package.json
+ @NODE_ENV= $(PKG) install
+ @touch node_modules
+
+lint: .FORCE
+ eslint browser.js debug.js index.js node.js
+
+test-node: .FORCE
+ istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
+
+test-browser: .FORCE
+ mkdir -p dist
+
+ @$(BROWSERIFY) \
+ --standalone debug \
+ . > dist/debug.js
+
+ karma start --single-run
+ rimraf dist
+
+test: .FORCE
+ concurrently \
+ "make test-node" \
+ "make test-browser"
+
+coveralls:
+ cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
+
+.PHONY: all install clean distclean
diff --git a/node_modules/express-session/node_modules/debug/README.md b/node_modules/express-session/node_modules/debug/README.md
new file mode 100644
index 00000000..f67be6b3
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/README.md
@@ -0,0 +1,312 @@
+# debug
+[](https://travis-ci.org/visionmedia/debug) [](https://coveralls.io/github/visionmedia/debug?branch=master) [](https://visionmedia-community-slackin.now.sh/) [](#backers)
+[](#sponsors)
+
+
+
+A tiny node.js debugging utility modelled after node core's debugging technique.
+
+**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
+
+## Installation
+
+```bash
+$ npm install debug
+```
+
+## Usage
+
+`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
+
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+ , http = require('http')
+ , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+ debug(req.method + ' ' + req.url);
+ res.end('hello\n');
+}).listen(3000, function(){
+ debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+ debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+ 
+
+ 
+
+#### Windows note
+
+ On Windows the environment variable is set using the `set` command.
+
+ ```cmd
+ set DEBUG=*,-not_this
+ ```
+
+ Note that PowerShell uses different syntax to set environment variables.
+
+ ```cmd
+ $env:DEBUG = "*,-not_this"
+ ```
+
+Then, run the program to be debugged as usual.
+
+## Millisecond diff
+
+ When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+ 
+
+ When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+
+ 
+
+## Conventions
+
+ If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
+
+## Wildcards
+
+ The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+ You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
+
+## Environment Variables
+
+ When running through Node.js, you can set a few environment variables that will
+ change the behavior of the debug logging:
+
+| Name | Purpose |
+|-----------|-------------------------------------------------|
+| `DEBUG` | Enables/disables specific debugging namespaces. |
+| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
+| `DEBUG_DEPTH` | Object inspection depth. |
+| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
+
+
+ __Note:__ The environment variables beginning with `DEBUG_` end up being
+ converted into an Options object that gets used with `%o`/`%O` formatters.
+ See the Node.js documentation for
+ [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+ for the complete list.
+
+## Formatters
+
+
+ Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
+
+| Formatter | Representation |
+|-----------|----------------|
+| `%O` | Pretty-print an Object on multiple lines. |
+| `%o` | Pretty-print an Object all on a single line. |
+| `%s` | String. |
+| `%d` | Number (both integer and float). |
+| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
+| `%%` | Single percent sign ('%'). This does not consume an argument. |
+
+### Custom formatters
+
+ You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
+
+```js
+const createDebug = require('debug')
+createDebug.formatters.h = (v) => {
+ return v.toString('hex')
+}
+
+// âŠelsewhere
+const debug = createDebug('foo')
+debug('this is hex: %h', new Buffer('hello world'))
+// foo this is hex: 68656c6c6f20776f726c6421 +0ms
+```
+
+## Browser support
+ You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+ or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+ if you don't want to build it yourself.
+
+ Debug's enable state is currently persisted by `localStorage`.
+ Consider the situation shown below where you have `worker:a` and `worker:b`,
+ and wish to debug both. You can enable this using `localStorage.debug`:
+
+```js
+localStorage.debug = 'worker:*'
+```
+
+And then refresh the page.
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+ a('doing some work');
+}, 1000);
+
+setInterval(function(){
+ b('doing some work');
+}, 1200);
+```
+
+#### Web Inspector Colors
+
+ Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+ option. These are WebKit web inspectors, Firefox ([since version
+ 31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+ and the Firebug plugin for Firefox (any version).
+
+ Colored output looks something like:
+
+ 
+
+
+## Output streams
+
+ By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
+
+Example _stdout.js_:
+
+```js
+var debug = require('debug');
+var error = debug('app:error');
+
+// by default stderr is used
+error('goes to stderr!');
+
+var log = debug('app:log');
+// set this namespace to log via console.log
+log.log = console.log.bind(console); // don't forget to bind to console!
+log('goes to stdout');
+error('still goes to stderr!');
+
+// set all output to go via console.info
+// overrides all per-namespace log settings
+debug.log = console.info.bind(console);
+error('now goes to stdout via console.info');
+log('still goes to stdout, but via console.info now');
+```
+
+
+## Authors
+
+ - TJ Holowaychuk
+ - Nathan Rajlich
+ - Andrew Rhyne
+
+## Backers
+
+Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Sponsors
+
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014-2016 TJ Holowaychuk <tj@vision-media.ca>
+
+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/express-session/node_modules/debug/component.json b/node_modules/express-session/node_modules/debug/component.json
new file mode 100644
index 00000000..9de26410
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/component.json
@@ -0,0 +1,19 @@
+{
+ "name": "debug",
+ "repo": "visionmedia/debug",
+ "description": "small debugging utility",
+ "version": "2.6.9",
+ "keywords": [
+ "debug",
+ "log",
+ "debugger"
+ ],
+ "main": "src/browser.js",
+ "scripts": [
+ "src/browser.js",
+ "src/debug.js"
+ ],
+ "dependencies": {
+ "rauchg/ms.js": "0.7.1"
+ }
+}
diff --git a/node_modules/express-session/node_modules/debug/karma.conf.js b/node_modules/express-session/node_modules/debug/karma.conf.js
new file mode 100644
index 00000000..103a82d1
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/karma.conf.js
@@ -0,0 +1,70 @@
+// Karma configuration
+// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
+
+module.exports = function(config) {
+ config.set({
+
+ // base path that will be used to resolve all patterns (eg. files, exclude)
+ basePath: '',
+
+
+ // frameworks to use
+ // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+ frameworks: ['mocha', 'chai', 'sinon'],
+
+
+ // list of files / patterns to load in the browser
+ files: [
+ 'dist/debug.js',
+ 'test/*spec.js'
+ ],
+
+
+ // list of files to exclude
+ exclude: [
+ 'src/node.js'
+ ],
+
+
+ // preprocess matching files before serving them to the browser
+ // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+ preprocessors: {
+ },
+
+ // test results reporter to use
+ // possible values: 'dots', 'progress'
+ // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+ reporters: ['progress'],
+
+
+ // web server port
+ port: 9876,
+
+
+ // enable / disable colors in the output (reporters and logs)
+ colors: true,
+
+
+ // level of logging
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: true,
+
+
+ // start these browsers
+ // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+ browsers: ['PhantomJS'],
+
+
+ // Continuous Integration mode
+ // if true, Karma captures browsers, runs the tests and exits
+ singleRun: false,
+
+ // Concurrency level
+ // how many browser should be started simultaneous
+ concurrency: Infinity
+ })
+}
diff --git a/node_modules/express-session/node_modules/debug/node.js b/node_modules/express-session/node_modules/debug/node.js
new file mode 100644
index 00000000..7fc36fe6
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/node_modules/express-session/node_modules/debug/package.json b/node_modules/express-session/node_modules/debug/package.json
new file mode 100644
index 00000000..dc787ba7
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "debug",
+ "version": "2.6.9",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/visionmedia/debug.git"
+ },
+ "description": "small debugging utility",
+ "keywords": [
+ "debug",
+ "log",
+ "debugger"
+ ],
+ "author": "TJ Holowaychuk ",
+ "contributors": [
+ "Nathan Rajlich (http://n8.io)",
+ "Andrew Rhyne "
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ },
+ "devDependencies": {
+ "browserify": "9.0.3",
+ "chai": "^3.5.0",
+ "concurrently": "^3.1.0",
+ "coveralls": "^2.11.15",
+ "eslint": "^3.12.1",
+ "istanbul": "^0.4.5",
+ "karma": "^1.3.0",
+ "karma-chai": "^0.1.0",
+ "karma-mocha": "^1.3.0",
+ "karma-phantomjs-launcher": "^1.0.2",
+ "karma-sinon": "^1.0.5",
+ "mocha": "^3.2.0",
+ "mocha-lcov-reporter": "^1.2.0",
+ "rimraf": "^2.5.4",
+ "sinon": "^1.17.6",
+ "sinon-chai": "^2.8.0"
+ },
+ "main": "./src/index.js",
+ "browser": "./src/browser.js",
+ "component": {
+ "scripts": {
+ "debug/index.js": "browser.js",
+ "debug/debug.js": "debug.js"
+ }
+ }
+}
diff --git a/node_modules/express-session/node_modules/debug/src/browser.js b/node_modules/express-session/node_modules/debug/src/browser.js
new file mode 100644
index 00000000..71069249
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/src/browser.js
@@ -0,0 +1,185 @@
+/**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = 'undefined' != typeof chrome
+ && 'undefined' != typeof chrome.storage
+ ? chrome.storage.local
+ : localstorage();
+
+/**
+ * Colors.
+ */
+
+exports.colors = [
+ 'lightseagreen',
+ 'forestgreen',
+ 'goldenrod',
+ 'dodgerblue',
+ 'darkorchid',
+ 'crimson'
+];
+
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+
+function useColors() {
+ // NB: In an Electron preload script, document will be defined but not fully
+ // initialized. Since we know we're in Chrome, we'll just detect this case
+ // explicitly
+ if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
+ return true;
+ }
+
+ // is webkit? http://stackoverflow.com/a/16459606/376773
+ // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+ return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+ // is firebug? http://stackoverflow.com/a/398120/376773
+ (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+ // is firefox >= v31?
+ // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+ (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+ // double check webkit in userAgent just in case we are in a worker
+ (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+}
+
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+exports.formatters.j = function(v) {
+ try {
+ return JSON.stringify(v);
+ } catch (err) {
+ return '[UnexpectedJSONParseError]: ' + err.message;
+ }
+};
+
+
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+ var useColors = this.useColors;
+
+ args[0] = (useColors ? '%c' : '')
+ + this.namespace
+ + (useColors ? ' %c' : ' ')
+ + args[0]
+ + (useColors ? '%c ' : ' ')
+ + '+' + exports.humanize(this.diff);
+
+ if (!useColors) return;
+
+ var c = 'color: ' + this.color;
+ args.splice(1, 0, c, 'color: inherit')
+
+ // the final "%c" is somewhat tricky, because there could be other
+ // arguments passed either before or after the %c, so we need to
+ // figure out the correct index to insert the CSS into
+ var index = 0;
+ var lastC = 0;
+ args[0].replace(/%[a-zA-Z%]/g, function(match) {
+ if ('%%' === match) return;
+ index++;
+ if ('%c' === match) {
+ // we only are interested in the *last* %c
+ // (the user may have provided their own)
+ lastC = index;
+ }
+ });
+
+ args.splice(lastC, 0, c);
+}
+
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+function log() {
+ // this hackery is required for IE8/9, where
+ // the `console.log` function doesn't have 'apply'
+ return 'object' === typeof console
+ && console.log
+ && Function.prototype.apply.call(console.log, console, arguments);
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+ try {
+ if (null == namespaces) {
+ exports.storage.removeItem('debug');
+ } else {
+ exports.storage.debug = namespaces;
+ }
+ } catch(e) {}
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+ var r;
+ try {
+ r = exports.storage.debug;
+ } catch(e) {}
+
+ // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+ if (!r && typeof process !== 'undefined' && 'env' in process) {
+ r = process.env.DEBUG;
+ }
+
+ return r;
+}
+
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+exports.enable(load());
+
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+function localstorage() {
+ try {
+ return window.localStorage;
+ } catch (e) {}
+}
diff --git a/node_modules/express-session/node_modules/debug/src/debug.js b/node_modules/express-session/node_modules/debug/src/debug.js
new file mode 100644
index 00000000..6a5e3fc9
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/src/debug.js
@@ -0,0 +1,202 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
+
+/**
+ * The currently active debug mode names, and names to skip.
+ */
+
+exports.names = [];
+exports.skips = [];
+
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+exports.formatters = {};
+
+/**
+ * Previous log timestamp.
+ */
+
+var prevTime;
+
+/**
+ * Select a color.
+ * @param {String} namespace
+ * @return {Number}
+ * @api private
+ */
+
+function selectColor(namespace) {
+ var hash = 0, i;
+
+ for (i in namespace) {
+ hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
+ hash |= 0; // Convert to 32bit integer
+ }
+
+ return exports.colors[Math.abs(hash) % exports.colors.length];
+}
+
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+function createDebug(namespace) {
+
+ function debug() {
+ // disabled?
+ if (!debug.enabled) return;
+
+ var self = debug;
+
+ // set `diff` timestamp
+ var curr = +new Date();
+ var ms = curr - (prevTime || curr);
+ self.diff = ms;
+ self.prev = prevTime;
+ self.curr = curr;
+ prevTime = curr;
+
+ // turn the `arguments` into a proper Array
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; i++) {
+ args[i] = arguments[i];
+ }
+
+ args[0] = exports.coerce(args[0]);
+
+ if ('string' !== typeof args[0]) {
+ // anything else let's inspect with %O
+ args.unshift('%O');
+ }
+
+ // apply any `formatters` transformations
+ var index = 0;
+ args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+ // if we encounter an escaped % then don't increase the array index
+ if (match === '%%') return match;
+ index++;
+ var formatter = exports.formatters[format];
+ if ('function' === typeof formatter) {
+ var val = args[index];
+ match = formatter.call(self, val);
+
+ // now we need to remove `args[index]` since it's inlined in the `format`
+ args.splice(index, 1);
+ index--;
+ }
+ return match;
+ });
+
+ // apply env-specific formatting (colors, etc.)
+ exports.formatArgs.call(self, args);
+
+ var logFn = debug.log || exports.log || console.log.bind(console);
+ logFn.apply(self, args);
+ }
+
+ debug.namespace = namespace;
+ debug.enabled = exports.enabled(namespace);
+ debug.useColors = exports.useColors();
+ debug.color = selectColor(namespace);
+
+ // env-specific initialization logic for debug instances
+ if ('function' === typeof exports.init) {
+ exports.init(debug);
+ }
+
+ return debug;
+}
+
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+function enable(namespaces) {
+ exports.save(namespaces);
+
+ exports.names = [];
+ exports.skips = [];
+
+ var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+ var len = split.length;
+
+ for (var i = 0; i < len; i++) {
+ if (!split[i]) continue; // ignore empty strings
+ namespaces = split[i].replace(/\*/g, '.*?');
+ if (namespaces[0] === '-') {
+ exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+ } else {
+ exports.names.push(new RegExp('^' + namespaces + '$'));
+ }
+ }
+}
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+function disable() {
+ exports.enable('');
+}
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+function enabled(name) {
+ var i, len;
+ for (i = 0, len = exports.skips.length; i < len; i++) {
+ if (exports.skips[i].test(name)) {
+ return false;
+ }
+ }
+ for (i = 0, len = exports.names.length; i < len; i++) {
+ if (exports.names[i].test(name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+function coerce(val) {
+ if (val instanceof Error) return val.stack || val.message;
+ return val;
+}
diff --git a/node_modules/express-session/node_modules/debug/src/index.js b/node_modules/express-session/node_modules/debug/src/index.js
new file mode 100644
index 00000000..e12cf4d5
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * Detect Electron renderer process, which is node, but we should
+ * treat as a browser.
+ */
+
+if (typeof process !== 'undefined' && process.type === 'renderer') {
+ module.exports = require('./browser.js');
+} else {
+ module.exports = require('./node.js');
+}
diff --git a/node_modules/express-session/node_modules/debug/src/inspector-log.js b/node_modules/express-session/node_modules/debug/src/inspector-log.js
new file mode 100644
index 00000000..60ea6c04
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/src/inspector-log.js
@@ -0,0 +1,15 @@
+module.exports = inspectorLog;
+
+// black hole
+const nullStream = new (require('stream').Writable)();
+nullStream._write = () => {};
+
+/**
+ * Outputs a `console.log()` to the Node.js Inspector console *only*.
+ */
+function inspectorLog() {
+ const stdout = console._stdout;
+ console._stdout = nullStream;
+ console.log.apply(console, arguments);
+ console._stdout = stdout;
+}
diff --git a/node_modules/express-session/node_modules/debug/src/node.js b/node_modules/express-session/node_modules/debug/src/node.js
new file mode 100644
index 00000000..b15109c9
--- /dev/null
+++ b/node_modules/express-session/node_modules/debug/src/node.js
@@ -0,0 +1,248 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+var util = require('util');
+
+/**
+ * This is the Node.js implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.init = init;
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+
+/**
+ * Colors.
+ */
+
+exports.colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Build up the default `inspectOpts` object from the environment variables.
+ *
+ * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
+ */
+
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+ return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+ // camel-case
+ var prop = key
+ .substring(6)
+ .toLowerCase()
+ .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
+
+ // coerce string value into JS value
+ var val = process.env[key];
+ if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
+ else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
+ else if (val === 'null') val = null;
+ else val = Number(val);
+
+ obj[prop] = val;
+ return obj;
+}, {});
+
+/**
+ * The file descriptor to write the `debug()` calls to.
+ * Set the `DEBUG_FD` env variable to override with another value. i.e.:
+ *
+ * $ DEBUG_FD=3 node script.js 3>debug.log
+ */
+
+var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
+
+if (1 !== fd && 2 !== fd) {
+ util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()
+}
+
+var stream = 1 === fd ? process.stdout :
+ 2 === fd ? process.stderr :
+ createWritableStdioStream(fd);
+
+/**
+ * Is stdout a TTY? Colored output is enabled when `true`.
+ */
+
+function useColors() {
+ return 'colors' in exports.inspectOpts
+ ? Boolean(exports.inspectOpts.colors)
+ : tty.isatty(fd);
+}
+
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+exports.formatters.o = function(v) {
+ this.inspectOpts.colors = this.useColors;
+ return util.inspect(v, this.inspectOpts)
+ .split('\n').map(function(str) {
+ return str.trim()
+ }).join(' ');
+};
+
+/**
+ * Map %o to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+exports.formatters.O = function(v) {
+ this.inspectOpts.colors = this.useColors;
+ return util.inspect(v, this.inspectOpts);
+};
+
+/**
+ * Adds ANSI color escape codes if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+ var name = this.namespace;
+ var useColors = this.useColors;
+
+ if (useColors) {
+ var c = this.color;
+ var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
+
+ args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+ args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
+ } else {
+ args[0] = new Date().toUTCString()
+ + ' ' + name + ' ' + args[0];
+ }
+}
+
+/**
+ * Invokes `util.format()` with the specified arguments and writes to `stream`.
+ */
+
+function log() {
+ return stream.write(util.format.apply(util, arguments) + '\n');
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+ if (null == namespaces) {
+ // If you set a process.env field to null or undefined, it gets cast to the
+ // string 'null' or 'undefined'. Just delete instead.
+ delete process.env.DEBUG;
+ } else {
+ process.env.DEBUG = namespaces;
+ }
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+ return process.env.DEBUG;
+}
+
+/**
+ * Copied from `node/src/node.js`.
+ *
+ * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
+ * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
+ */
+
+function createWritableStdioStream (fd) {
+ var stream;
+ var tty_wrap = process.binding('tty_wrap');
+
+ // Note stream._type is used for test-module-load-list.js
+
+ switch (tty_wrap.guessHandleType(fd)) {
+ case 'TTY':
+ stream = new tty.WriteStream(fd);
+ stream._type = 'tty';
+
+ // Hack to have stream not keep the event loop alive.
+ // See https://github.com/joyent/node/issues/1726
+ if (stream._handle && stream._handle.unref) {
+ stream._handle.unref();
+ }
+ break;
+
+ case 'FILE':
+ var fs = require('fs');
+ stream = new fs.SyncWriteStream(fd, { autoClose: false });
+ stream._type = 'fs';
+ break;
+
+ case 'PIPE':
+ case 'TCP':
+ var net = require('net');
+ stream = new net.Socket({
+ fd: fd,
+ readable: false,
+ writable: true
+ });
+
+ // FIXME Should probably have an option in net.Socket to create a
+ // stream from an existing fd which is writable only. But for now
+ // we'll just add this hack and set the `readable` member to false.
+ // Test: ./node test/fixtures/echo.js < /etc/passwd
+ stream.readable = false;
+ stream.read = null;
+ stream._type = 'pipe';
+
+ // FIXME Hack to have stream not keep the event loop alive.
+ // See https://github.com/joyent/node/issues/1726
+ if (stream._handle && stream._handle.unref) {
+ stream._handle.unref();
+ }
+ break;
+
+ default:
+ // Probably an error on in uv_guess_handle()
+ throw new Error('Implement me. Unknown stream file type!');
+ }
+
+ // For supporting legacy API we put the FD here.
+ stream.fd = fd;
+
+ stream._isStdio = true;
+
+ return stream;
+}
+
+/**
+ * Init logic for `debug` instances.
+ *
+ * Create a new `inspectOpts` object in case `useColors` is set
+ * differently for a particular `debug` instance.
+ */
+
+function init (debug) {
+ debug.inspectOpts = {};
+
+ var keys = Object.keys(exports.inspectOpts);
+ for (var i = 0; i < keys.length; i++) {
+ debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+ }
+}
+
+/**
+ * Enable namespaces listed in `process.env.DEBUG` initially.
+ */
+
+exports.enable(load());
diff --git a/node_modules/express-session/node_modules/ms/index.js b/node_modules/express-session/node_modules/ms/index.js
new file mode 100644
index 00000000..6a522b16
--- /dev/null
+++ b/node_modules/express-session/node_modules/ms/index.js
@@ -0,0 +1,152 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ * - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+ options = options || {};
+ var type = typeof val;
+ if (type === 'string' && val.length > 0) {
+ return parse(val);
+ } else if (type === 'number' && isNaN(val) === false) {
+ return options.long ? fmtLong(val) : fmtShort(val);
+ }
+ throw new Error(
+ 'val is not a non-empty string or a valid number. val=' +
+ JSON.stringify(val)
+ );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+ str = String(str);
+ if (str.length > 100) {
+ return;
+ }
+ var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
+ str
+ );
+ if (!match) {
+ return;
+ }
+ var n = parseFloat(match[1]);
+ var type = (match[2] || 'ms').toLowerCase();
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'yrs':
+ case 'yr':
+ case 'y':
+ return n * y;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * d;
+ case 'hours':
+ case 'hour':
+ case 'hrs':
+ case 'hr':
+ case 'h':
+ return n * h;
+ case 'minutes':
+ case 'minute':
+ case 'mins':
+ case 'min':
+ case 'm':
+ return n * m;
+ case 'seconds':
+ case 'second':
+ case 'secs':
+ case 'sec':
+ case 's':
+ return n * s;
+ case 'milliseconds':
+ case 'millisecond':
+ case 'msecs':
+ case 'msec':
+ case 'ms':
+ return n;
+ default:
+ return undefined;
+ }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+ if (ms >= d) {
+ return Math.round(ms / d) + 'd';
+ }
+ if (ms >= h) {
+ return Math.round(ms / h) + 'h';
+ }
+ if (ms >= m) {
+ return Math.round(ms / m) + 'm';
+ }
+ if (ms >= s) {
+ return Math.round(ms / s) + 's';
+ }
+ return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+ return plural(ms, d, 'day') ||
+ plural(ms, h, 'hour') ||
+ plural(ms, m, 'minute') ||
+ plural(ms, s, 'second') ||
+ ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+ if (ms < n) {
+ return;
+ }
+ if (ms < n * 1.5) {
+ return Math.floor(ms / n) + ' ' + name;
+ }
+ return Math.ceil(ms / n) + ' ' + name + 's';
+}
diff --git a/node_modules/express-session/node_modules/ms/license.md b/node_modules/express-session/node_modules/ms/license.md
new file mode 100644
index 00000000..69b61253
--- /dev/null
+++ b/node_modules/express-session/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+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/express-session/node_modules/ms/package.json b/node_modules/express-session/node_modules/ms/package.json
new file mode 100644
index 00000000..6a31c81f
--- /dev/null
+++ b/node_modules/express-session/node_modules/ms/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "ms",
+ "version": "2.0.0",
+ "description": "Tiny milisecond conversion utility",
+ "repository": "zeit/ms",
+ "main": "./index",
+ "files": [
+ "index.js"
+ ],
+ "scripts": {
+ "precommit": "lint-staged",
+ "lint": "eslint lib/* bin/*",
+ "test": "mocha tests.js"
+ },
+ "eslintConfig": {
+ "extends": "eslint:recommended",
+ "env": {
+ "node": true,
+ "es6": true
+ }
+ },
+ "lint-staged": {
+ "*.js": [
+ "npm run lint",
+ "prettier --single-quote --write",
+ "git add"
+ ]
+ },
+ "license": "MIT",
+ "devDependencies": {
+ "eslint": "3.19.0",
+ "expect.js": "0.3.1",
+ "husky": "0.13.3",
+ "lint-staged": "3.4.1",
+ "mocha": "3.4.1"
+ }
+}
diff --git a/node_modules/express-session/node_modules/ms/readme.md b/node_modules/express-session/node_modules/ms/readme.md
new file mode 100644
index 00000000..84a9974c
--- /dev/null
+++ b/node_modules/express-session/node_modules/ms/readme.md
@@ -0,0 +1,51 @@
+# ms
+
+[](https://travis-ci.org/zeit/ms)
+[](https://zeit.chat/)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days') // 172800000
+ms('1d') // 86400000
+ms('10h') // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h') // 7200000
+ms('1m') // 60000
+ms('5s') // 5000
+ms('1y') // 31557600000
+ms('100') // 100
+```
+
+### Convert from milliseconds
+
+```js
+ms(60000) // "1m"
+ms(2 * 60000) // "2m"
+ms(ms('10 hours')) // "10h"
+```
+
+### Time format written-out
+
+```js
+ms(60000, { long: true }) // "1 minute"
+ms(2 * 60000, { long: true }) // "2 minutes"
+ms(ms('10 hours'), { long: true }) // "10 hours"
+```
+
+## Features
+
+- Works both in [node](https://nodejs.org) and in the browser.
+- If a number is supplied to `ms`, a string with a unit is returned.
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`).
+- If you pass a string with a number and a valid unit, the number of equivalent ms is returned.
+
+## Caught a bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/node_modules/express-session/package.json b/node_modules/express-session/package.json
new file mode 100644
index 00000000..7039d1d4
--- /dev/null
+++ b/node_modules/express-session/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "express-session",
+ "version": "1.18.2",
+ "description": "Simple session middleware for Express",
+ "author": "TJ Holowaychuk (http://tjholowaychuk.com)",
+ "contributors": [
+ "Douglas Christopher Wilson ",
+ "Joe Wagner "
+ ],
+ "repository": "expressjs/session",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "0.7.2",
+ "cookie-signature": "1.0.7",
+ "debug": "2.6.9",
+ "depd": "~2.0.0",
+ "on-headers": "~1.1.0",
+ "parseurl": "~1.3.3",
+ "safe-buffer": "5.2.1",
+ "uid-safe": "~2.1.5"
+ },
+ "devDependencies": {
+ "after": "0.8.2",
+ "cookie-parser": "1.4.6",
+ "eslint": "8.56.0",
+ "eslint-plugin-markdown": "3.0.1",
+ "express": "4.17.3",
+ "mocha": "10.8.2",
+ "nyc": "15.1.0",
+ "supertest": "6.3.4"
+ },
+ "files": [
+ "session/",
+ "HISTORY.md",
+ "index.js"
+ ],
+ "engines": {
+ "node": ">= 0.8.0"
+ },
+ "scripts": {
+ "lint": "eslint . && node ./scripts/lint-readme.js",
+ "test": "./test/support/gencert.sh && mocha --require test/support/env --check-leaks --bail --no-exit --reporter spec test/",
+ "test-ci": "nyc --reporter=lcov --reporter=text npm test",
+ "test-cov": "nyc npm test",
+ "version": "node scripts/version-history.js && git add HISTORY.md"
+ }
+}
diff --git a/node_modules/express-session/session/cookie.js b/node_modules/express-session/session/cookie.js
new file mode 100644
index 00000000..8bb5907b
--- /dev/null
+++ b/node_modules/express-session/session/cookie.js
@@ -0,0 +1,152 @@
+/*!
+ * Connect - session - Cookie
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module dependencies.
+ */
+
+var cookie = require('cookie')
+var deprecate = require('depd')('express-session')
+
+/**
+ * Initialize a new `Cookie` with the given `options`.
+ *
+ * @param {IncomingMessage} req
+ * @param {Object} options
+ * @api private
+ */
+
+var Cookie = module.exports = function Cookie(options) {
+ this.path = '/';
+ this.maxAge = null;
+ this.httpOnly = true;
+
+ if (options) {
+ if (typeof options !== 'object') {
+ throw new TypeError('argument options must be a object')
+ }
+
+ for (var key in options) {
+ if (key !== 'data') {
+ this[key] = options[key]
+ }
+ }
+ }
+
+ if (this.originalMaxAge === undefined || this.originalMaxAge === null) {
+ this.originalMaxAge = this.maxAge
+ }
+};
+
+/*!
+ * Prototype.
+ */
+
+Cookie.prototype = {
+
+ /**
+ * Set expires `date`.
+ *
+ * @param {Date} date
+ * @api public
+ */
+
+ set expires(date) {
+ this._expires = date;
+ this.originalMaxAge = this.maxAge;
+ },
+
+ /**
+ * Get expires `date`.
+ *
+ * @return {Date}
+ * @api public
+ */
+
+ get expires() {
+ return this._expires;
+ },
+
+ /**
+ * Set expires via max-age in `ms`.
+ *
+ * @param {Number} ms
+ * @api public
+ */
+
+ set maxAge(ms) {
+ if (ms && typeof ms !== 'number' && !(ms instanceof Date)) {
+ throw new TypeError('maxAge must be a number or Date')
+ }
+
+ if (ms instanceof Date) {
+ deprecate('maxAge as Date; pass number of milliseconds instead')
+ }
+
+ this.expires = typeof ms === 'number'
+ ? new Date(Date.now() + ms)
+ : ms;
+ },
+
+ /**
+ * Get expires max-age in `ms`.
+ *
+ * @return {Number}
+ * @api public
+ */
+
+ get maxAge() {
+ return this.expires instanceof Date
+ ? this.expires.valueOf() - Date.now()
+ : this.expires;
+ },
+
+ /**
+ * Return cookie data object.
+ *
+ * @return {Object}
+ * @api private
+ */
+
+ get data() {
+ return {
+ originalMaxAge: this.originalMaxAge,
+ partitioned: this.partitioned,
+ priority: this.priority
+ , expires: this._expires
+ , secure: this.secure
+ , httpOnly: this.httpOnly
+ , domain: this.domain
+ , path: this.path
+ , sameSite: this.sameSite
+ }
+ },
+
+ /**
+ * Return a serialized cookie string.
+ *
+ * @return {String}
+ * @api public
+ */
+
+ serialize: function(name, val){
+ return cookie.serialize(name, val, this.data);
+ },
+
+ /**
+ * Return JSON representation of this cookie.
+ *
+ * @return {Object}
+ * @api private
+ */
+
+ toJSON: function(){
+ return this.data;
+ }
+};
diff --git a/node_modules/express-session/session/memory.js b/node_modules/express-session/session/memory.js
new file mode 100644
index 00000000..11ed686c
--- /dev/null
+++ b/node_modules/express-session/session/memory.js
@@ -0,0 +1,187 @@
+/*!
+ * express-session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2015 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var Store = require('./store')
+var util = require('util')
+
+/**
+ * Shim setImmediate for node.js < 0.10
+ * @private
+ */
+
+/* istanbul ignore next */
+var defer = typeof setImmediate === 'function'
+ ? setImmediate
+ : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
+
+/**
+ * Module exports.
+ */
+
+module.exports = MemoryStore
+
+/**
+ * A session store in memory.
+ * @public
+ */
+
+function MemoryStore() {
+ Store.call(this)
+ this.sessions = Object.create(null)
+}
+
+/**
+ * Inherit from Store.
+ */
+
+util.inherits(MemoryStore, Store)
+
+/**
+ * Get all active sessions.
+ *
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.all = function all(callback) {
+ var sessionIds = Object.keys(this.sessions)
+ var sessions = Object.create(null)
+
+ for (var i = 0; i < sessionIds.length; i++) {
+ var sessionId = sessionIds[i]
+ var session = getSession.call(this, sessionId)
+
+ if (session) {
+ sessions[sessionId] = session;
+ }
+ }
+
+ callback && defer(callback, null, sessions)
+}
+
+/**
+ * Clear all sessions.
+ *
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.clear = function clear(callback) {
+ this.sessions = Object.create(null)
+ callback && defer(callback)
+}
+
+/**
+ * Destroy the session associated with the given session ID.
+ *
+ * @param {string} sessionId
+ * @public
+ */
+
+MemoryStore.prototype.destroy = function destroy(sessionId, callback) {
+ delete this.sessions[sessionId]
+ callback && defer(callback)
+}
+
+/**
+ * Fetch session by the given session ID.
+ *
+ * @param {string} sessionId
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.get = function get(sessionId, callback) {
+ defer(callback, null, getSession.call(this, sessionId))
+}
+
+/**
+ * Commit the given session associated with the given sessionId to the store.
+ *
+ * @param {string} sessionId
+ * @param {object} session
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.set = function set(sessionId, session, callback) {
+ this.sessions[sessionId] = JSON.stringify(session)
+ callback && defer(callback)
+}
+
+/**
+ * Get number of active sessions.
+ *
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.length = function length(callback) {
+ this.all(function (err, sessions) {
+ if (err) return callback(err)
+ callback(null, Object.keys(sessions).length)
+ })
+}
+
+/**
+ * Touch the given session object associated with the given session ID.
+ *
+ * @param {string} sessionId
+ * @param {object} session
+ * @param {function} callback
+ * @public
+ */
+
+MemoryStore.prototype.touch = function touch(sessionId, session, callback) {
+ var currentSession = getSession.call(this, sessionId)
+
+ if (currentSession) {
+ // update expiration
+ currentSession.cookie = session.cookie
+ this.sessions[sessionId] = JSON.stringify(currentSession)
+ }
+
+ callback && defer(callback)
+}
+
+/**
+ * Get session from the store.
+ * @private
+ */
+
+function getSession(sessionId) {
+ var sess = this.sessions[sessionId]
+
+ if (!sess) {
+ return
+ }
+
+ // parse
+ sess = JSON.parse(sess)
+
+ if (sess.cookie) {
+ var expires = typeof sess.cookie.expires === 'string'
+ ? new Date(sess.cookie.expires)
+ : sess.cookie.expires
+
+ // destroy expired session
+ if (expires && expires <= Date.now()) {
+ delete this.sessions[sessionId]
+ return
+ }
+ }
+
+ return sess
+}
diff --git a/node_modules/express-session/session/session.js b/node_modules/express-session/session/session.js
new file mode 100644
index 00000000..fee7608c
--- /dev/null
+++ b/node_modules/express-session/session/session.js
@@ -0,0 +1,143 @@
+/*!
+ * Connect - session - Session
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Expose Session.
+ */
+
+module.exports = Session;
+
+/**
+ * Create a new `Session` with the given request and `data`.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} data
+ * @api private
+ */
+
+function Session(req, data) {
+ Object.defineProperty(this, 'req', { value: req });
+ Object.defineProperty(this, 'id', { value: req.sessionID });
+
+ if (typeof data === 'object' && data !== null) {
+ // merge data into this, ignoring prototype properties
+ for (var prop in data) {
+ if (!(prop in this)) {
+ this[prop] = data[prop]
+ }
+ }
+ }
+}
+
+/**
+ * Update reset `.cookie.maxAge` to prevent
+ * the cookie from expiring when the
+ * session is still active.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'touch', function touch() {
+ return this.resetMaxAge();
+});
+
+/**
+ * Reset `.maxAge` to `.originalMaxAge`.
+ *
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'resetMaxAge', function resetMaxAge() {
+ this.cookie.maxAge = this.cookie.originalMaxAge;
+ return this;
+});
+
+/**
+ * Save the session data with optional callback `fn(err)`.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'save', function save(fn) {
+ this.req.sessionStore.set(this.id, this, fn || function(){});
+ return this;
+});
+
+/**
+ * Re-loads the session data _without_ altering
+ * the maxAge properties. Invokes the callback `fn(err)`,
+ * after which time if no exception has occurred the
+ * `req.session` property will be a new `Session` object,
+ * although representing the same session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'reload', function reload(fn) {
+ var req = this.req
+ var store = this.req.sessionStore
+
+ store.get(this.id, function(err, sess){
+ if (err) return fn(err);
+ if (!sess) return fn(new Error('failed to load session'));
+ store.createSession(req, sess);
+ fn();
+ });
+ return this;
+});
+
+/**
+ * Destroy `this` session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'destroy', function destroy(fn) {
+ delete this.req.session;
+ this.req.sessionStore.destroy(this.id, fn);
+ return this;
+});
+
+/**
+ * Regenerate this request's session.
+ *
+ * @param {Function} fn
+ * @return {Session} for chaining
+ * @api public
+ */
+
+defineMethod(Session.prototype, 'regenerate', function regenerate(fn) {
+ this.req.sessionStore.regenerate(this.req, fn);
+ return this;
+});
+
+/**
+ * Helper function for creating a method on a prototype.
+ *
+ * @param {Object} obj
+ * @param {String} name
+ * @param {Function} fn
+ * @private
+ */
+function defineMethod(obj, name, fn) {
+ Object.defineProperty(obj, name, {
+ configurable: true,
+ enumerable: false,
+ value: fn,
+ writable: true
+ });
+};
diff --git a/node_modules/express-session/session/store.js b/node_modules/express-session/session/store.js
new file mode 100644
index 00000000..3793877e
--- /dev/null
+++ b/node_modules/express-session/session/store.js
@@ -0,0 +1,102 @@
+/*!
+ * Connect - session - Store
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+'use strict';
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var Cookie = require('./cookie')
+var EventEmitter = require('events').EventEmitter
+var Session = require('./session')
+var util = require('util')
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = Store
+
+/**
+ * Abstract base class for session stores.
+ * @public
+ */
+
+function Store () {
+ EventEmitter.call(this)
+}
+
+/**
+ * Inherit from EventEmitter.
+ */
+
+util.inherits(Store, EventEmitter)
+
+/**
+ * Re-generate the given requests's session.
+ *
+ * @param {IncomingRequest} req
+ * @return {Function} fn
+ * @api public
+ */
+
+Store.prototype.regenerate = function(req, fn){
+ var self = this;
+ this.destroy(req.sessionID, function(err){
+ self.generate(req);
+ fn(err);
+ });
+};
+
+/**
+ * Load a `Session` instance via the given `sid`
+ * and invoke the callback `fn(err, sess)`.
+ *
+ * @param {String} sid
+ * @param {Function} fn
+ * @api public
+ */
+
+Store.prototype.load = function(sid, fn){
+ var self = this;
+ this.get(sid, function(err, sess){
+ if (err) return fn(err);
+ if (!sess) return fn();
+ var req = { sessionID: sid, sessionStore: self };
+ fn(null, self.createSession(req, sess))
+ });
+};
+
+/**
+ * Create session from JSON `sess` data.
+ *
+ * @param {IncomingRequest} req
+ * @param {Object} sess
+ * @return {Session}
+ * @api private
+ */
+
+Store.prototype.createSession = function(req, sess){
+ var expires = sess.cookie.expires
+ var originalMaxAge = sess.cookie.originalMaxAge
+
+ sess.cookie = new Cookie(sess.cookie);
+
+ if (typeof expires === 'string') {
+ // convert expires to a Date object
+ sess.cookie.expires = new Date(expires)
+ }
+
+ // keep originalMaxAge intact
+ sess.cookie.originalMaxAge = originalMaxAge
+
+ req.session = new Session(req, sess);
+ return req.session;
+};
diff --git a/node_modules/helmet/CHANGELOG.md b/node_modules/helmet/CHANGELOG.md
new file mode 100644
index 00000000..24288456
--- /dev/null
+++ b/node_modules/helmet/CHANGELOG.md
@@ -0,0 +1,974 @@
+# Changelog
+
+## 8.1.0 - 2025-03-17
+
+### Changed
+
+- `Content-Security-Policy` gives a better error when a directive value, like `self`, should be quoted. See [#482](https://github.com/helmetjs/helmet/issues/482)
+
+## 8.0.0 - 2024-09-28
+
+### Changed
+
+- **Breaking:** `Strict-Transport-Security` now has a max-age of 365 days, up from 180
+- **Breaking:** `Content-Security-Policy` middleware now throws an error if a directive should have quotes but does not, such as `self` instead of `'self'`. See [#454](https://github.com/helmetjs/helmet/issues/454)
+- **Breaking:** `Content-Security-Policy`'s `getDefaultDirectives` now returns a deep copy. This only affects users who were mutating the result
+- **Breaking:** `Strict-Transport-Security` now throws an error when "includeSubDomains" option is misspelled. This was previously a warning
+
+### Removed
+
+- **Breaking:** Drop support for Node 16 and 17. Node 18+ is now required
+
+## 7.2.0 - 2024-09-28
+
+### Changed
+
+- `Content-Security-Policy` middleware now warns if a directive should have quotes but does not, such as `self` instead of `'self'`. This will be an error in future versions. See [#454](https://github.com/helmetjs/helmet/issues/454)
+
+## 7.1.0 - 2023-11-07
+
+### Added
+
+- `helmet.crossOriginEmbedderPolicy` now supports the `unsafe-none` directive. See [#477](https://github.com/helmetjs/helmet/pull/447)
+
+## 7.0.0 - 2023-05-06
+
+### Changed
+
+- **Breaking:** `Cross-Origin-Embedder-Policy` middleware is now disabled by default. See [#411](https://github.com/helmetjs/helmet/issues/411)
+
+### Removed
+
+- **Breaking:** Drop support for Node 14 and 15. Node 16+ is now required
+- **Breaking:** `Expect-CT` is no longer part of Helmet. If you still need it, you can use the [`expect-ct` package](https://www.npmjs.com/package/expect-ct). See [#378](https://github.com/helmetjs/helmet/issues/378)
+
+## 6.2.0 - 2023-05-06
+
+- Expose header names (e.g., `strictTransportSecurity` for the `Strict-Transport-Security` header, instead of `hsts`)
+- Rework documentation
+
+## 6.1.5 - 2023-04-11
+
+### Fixed
+
+- Fixed yet another issue with TypeScript exports. See [#420](https://github.com/helmetjs/helmet/pull/418)
+
+## 6.1.4 - 2023-04-10
+
+### Fixed
+
+- Fix another issue with TypeScript default exports. See [#418](https://github.com/helmetjs/helmet/pull/418)
+
+## 6.1.3 - 2023-04-10
+
+### Fixed
+
+- Fix issue with TypeScript default exports. See [#417](https://github.com/helmetjs/helmet/pull/417)
+
+## 6.1.2 - 2023-04-09
+
+### Fixed
+
+- Retored `main` to package to help with some build tools
+
+## 6.1.1 - 2023-04-08
+
+### Fixed
+
+- Fixed missing package metadata
+
+## 6.1.0 - 2023-04-08
+
+### Changed
+
+- Improve support for various TypeScript setups, including "nodenext". See [#405](https://github.com/helmetjs/helmet/pull/405)
+
+## 6.0.1 - 2022-11-29
+
+### Fixed
+
+- `crossOriginEmbedderPolicy` did not accept options at the top level. See [#390](https://github.com/helmetjs/helmet/issues/390)
+
+## 6.0.0 - 2022-08-26
+
+### Changed
+
+- **Breaking:** `helmet.contentSecurityPolicy` no longer sets `block-all-mixed-content` directive by default
+- **Breaking:** `helmet.expectCt` is no longer set by default. It can, however, be explicitly enabled. It will be removed in Helmet 7. See [#310](https://github.com/helmetjs/helmet/issues/310)
+- **Breaking:** Increase TypeScript strictness around some arguments. Only affects TypeScript users, and may not require any code changes. See [#369](https://github.com/helmetjs/helmet/issues/369)
+- `helmet.frameguard` no longer offers a specific error when trying to use `ALLOW-FROM`; it just says that it is unsupported. Only the error message has changed
+
+### Removed
+
+- **Breaking:** Dropped support for Node 12 and 13. Node 14+ is now required
+
+## 5.1.1 - 2022-07-23
+
+### Changed
+
+- Fix TypeScript bug with some TypeScript configurations. See [#375](https://github.com/helmetjs/helmet/pull/375) and [#359](https://github.com/helmetjs/helmet/issues/359)
+
+## 5.1.0 - 2022-05-17
+
+### Added
+
+- `Cross-Origin-Embedder-Policy`: support `credentialless` policy. See [#365](https://github.com/helmetjs/helmet/pull/365)
+- Documented how to set both `Content-Security-Policy` and `Content-Security-Policy-Report-Only`
+
+### Changed
+
+- Cleaned up some documentation around `Origin-Agent-Cluster`
+
+## 5.0.2 - 2022-01-22
+
+### Changed
+
+- Improve imports for CommonJS and ECMAScript modules. See [#345](https://github.com/helmetjs/helmet/pull/345)
+- Fixed some documentation
+
+## 5.0.1 - 2022-01-03
+
+### Changed
+
+- Fixed some documentation
+
+### Removed
+
+- Removed some unused internal code
+
+## 5.0.0 - 2022-01-02
+
+### Added
+
+- ECMAScript module imports (i.e., `import helmet from "helmet"` and `import { frameguard } from "helmet"`). See [#320](https://github.com/helmetjs/helmet/issues/320)
+
+### Changed
+
+- **Breaking:** `helmet.contentSecurityPolicy`: `useDefaults` option now defaults to `true`
+- **Breaking:** `helmet.contentSecurityPolicy`: `form-action` directive is now set to `'self'` by default
+- **Breaking:** `helmet.crossOriginEmbedderPolicy` is enabled by default
+- **Breaking:** `helmet.crossOriginOpenerPolicy` is enabled by default
+- **Breaking:** `helmet.crossOriginResourcePolicy` is enabled by default
+- **Breaking:** `helmet.originAgentCluster` is enabled by default
+- `helmet.frameguard`: add TypeScript editor autocomplete. See [#322](https://github.com/helmetjs/helmet/pull/322)
+- Top-level `helmet()` function is slightly faster
+
+### Removed
+
+- **Breaking:** Drop support for Node 10 and 11. Node 12+ is now required
+
+## 4.6.0 - 2021-05-01
+
+### Added
+
+- `helmet.contentSecurityPolicy`: the `useDefaults` option, defaulting to `false`, lets you selectively override defaults more easily
+- Explicitly define TypeScript types in `package.json`. See [#303](https://github.com/helmetjs/helmet/pull/303)
+
+## 4.5.0 - 2021-04-17
+
+### Added
+
+- `helmet.crossOriginEmbedderPolicy`: a new middleware for the `Cross-Origin-Embedder-Policy` header, disabled by default
+- `helmet.crossOriginOpenerPolicy`: a new middleware for the `Cross-Origin-Opener-Policy` header, disabled by default
+- `helmet.crossOriginResourcePolicy`: a new middleware for the `Cross-Origin-Resource-Policy` header, disabled by default
+
+### Changed
+
+- `true` enables a middleware with default options. Previously, this would fail with an error if the middleware was already enabled by default.
+- Log a warning when passing options to `originAgentCluster` at the top level
+
+### Fixed
+
+- Incorrect documentation
+
+## 4.4.1 - 2021-01-18
+
+### Changed
+
+- Shrink the published package by about 2.5 kB
+
+## 4.4.0 - 2021-01-17
+
+### Added
+
+- `helmet.originAgentCluster`: a new middleware for the `Origin-Agent-Cluster` header, disabled by default
+
+## 4.3.1 - 2020-12-27
+
+### Fixed
+
+- `helmet.contentSecurityPolicy`: broken TypeScript types. See [#283](https://github.com/helmetjs/helmet/issues/283)
+
+## 4.3.0 - 2020-12-27
+
+### Added
+
+- `helmet.contentSecurityPolicy`: setting the `default-src` to `helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc` disables it
+
+### Changed
+
+- `helmet.frameguard`: slightly improved error messages for non-strings
+
+## 4.2.0 - 2020-11-01
+
+### Added
+
+- `helmet.contentSecurityPolicy`: get the default directives with `contentSecurityPolicy.getDefaultDirectives()`
+
+### Changed
+
+- `helmet()` now supports objects that don't have `Object.prototype` in their chain, such as `Object.create(null)`, as options
+- `helmet.expectCt`: `max-age` is now first. See [#264](https://github.com/helmetjs/helmet/pull/264)
+
+## 4.1.1 - 2020-09-10
+
+### Changed
+
+- Fixed a few errors in the README
+
+## 4.1.0 - 2020-08-15
+
+### Added
+
+- `helmet.contentSecurityPolicy`:
+ - Directive values can now include functions, as they could in Helmet 3. See [#243](https://github.com/helmetjs/helmet/issues/243)
+
+### Changed
+
+- Helmet should now play more nicely with TypeScript
+
+### Removed
+
+- The `HelmetOptions` interface is no longer exported. This only affects TypeScript users. If you need the functionality back, see [this comment](https://github.com/helmetjs/helmet/issues/235#issuecomment-674016883)
+
+## 4.0.0 - 2020-08-02
+
+See the [Helmet 4 upgrade guide](https://github.com/helmetjs/helmet/wiki/Helmet-4-upgrade-guide) for help upgrading from Helmet 3.
+
+### Added
+
+- `helmet.contentSecurityPolicy`:
+ - If no `default-src` directive is supplied, an error is thrown
+ - Directive lists can be any iterable, not just arrays
+
+### Changed
+
+- This package no longer has dependencies. This should have no effect on end users, other than speeding up installation time.
+- `helmet.contentSecurityPolicy`:
+ - There is now a default set of directives if none are supplied
+ - Duplicate keys now throw an error. See [helmetjs/csp#73](https://github.com/helmetjs/csp/issues/73)
+ - This middleware is more lenient, allowing more directive names or values
+- `helmet.xssFilter` now disables the buggy XSS filter by default. See [#230](https://github.com/helmetjs/helmet/issues/230)
+
+### Removed
+
+- Dropped support for old Node versions. Node 10+ is now required
+- `helmet.featurePolicy`. If you still need it, use the `feature-policy` package on npm.
+- `helmet.hpkp`. If you still need it, use the `hpkp` package on npm.
+- `helmet.noCache`. If you still need it, use the `nocache` package on npm.
+- `helmet.contentSecurityPolicy`:
+ - Removed browser sniffing (including the `browserSniff` and `disableAndroid` parameters). See [helmetjs/csp#97](https://github.com/helmetjs/csp/issues/97)
+ - Removed conditional support. This includes directive functions and support for a function as the `reportOnly`. [Read this if you need help.](https://github.com/helmetjs/helmet/wiki/Conditionally-using-middleware)
+ - Removed a lot of checksâyou should be checking your CSP with a different tool
+ - Removed support for legacy headers (and therefore the `setAllHeaders` parameter). [Read this if you need help.](https://github.com/helmetjs/helmet/wiki/Setting-legacy-Content-Security-Policy-headers-in-Helmet-4)
+ - Removed the `loose` option
+ - Removed support for functions as directive values. You must supply an iterable of strings
+- `helmet.frameguard`:
+ - Dropped support for the `ALLOW-FROM` action. [Read more here.](https://github.com/helmetjs/helmet/wiki/How-to-use-X%E2%80%93Frame%E2%80%93Options's-%60ALLOW%E2%80%93FROM%60-directive)
+- `helmet.hidePoweredBy` no longer accepts arguments. See [this article](https://github.com/helmetjs/helmet/wiki/How-to-set-a-custom-X%E2%80%93Powered%E2%80%93By-header) to see how to replicate the removed behavior. See [#224](https://github.com/helmetjs/helmet/issues/224).
+- `helmet.hsts`:
+ - Dropped support for `includeSubdomains` with a lowercase D. See [#231](https://github.com/helmetjs/helmet/issues/231)
+ - Dropped support for `setIf`. [Read this if you need help.](https://github.com/helmetjs/helmet/wiki/Conditionally-using-middleware) See [#232](https://github.com/helmetjs/helmet/issues/232)
+- `helmet.xssFilter` no longer accepts options. Read ["How to disable blocking with X-XSS-Protection"](https://github.com/helmetjs/helmet/wiki/How-to-disable-blocking-with-X%E2%80%93XSS%E2%80%93Protection) and ["How to enable the `report` directive with X-XSS-Protection"](https://github.com/helmetjs/helmet/wiki/How-to-enable-the-%60report%60-directive-with-X%E2%80%93XSS%E2%80%93Protection) if you need the legacy behavior.
+
+## 3.23.3 - 2020-06-26
+
+### Changed
+
+- `helmet.expectCt` is no longer a separate package. This should have no effect on end users.
+- `helmet.frameguard` is no longer a separate package. This should have no effect on end users.
+
+## 3.23.2 - 2020-06-23
+
+### Changed
+
+- `helmet.dnsPrefetchControl` is no longer a separate package. This should have no effect on end users.
+
+## 3.23.1 - 2020-06-16
+
+### Changed
+
+- `helmet.ieNoOpen` is no longer a separate package. This should have no effect on end users.
+
+## 3.23.0 - 2020-06-12
+
+### Deprecated
+
+- `helmet.featurePolicy` is deprecated. Use the `feature-policy` module instead.
+
+## 3.22.1 - 2020-06-10
+
+### Changed
+
+- Rewrote internals in TypeScript. This should have no effect on end users.
+
+## 3.22.0 - 2020-03-24
+
+### Changed
+
+- Updated `helmet-csp` to v2.10.0
+ - Add support for the `allow-downloads` sandbox directive. See [helmet-csp#103](https://github.com/helmetjs/csp/pull/103)
+
+### Deprecated
+
+- `helmet.noCache` is deprecated. Use the `nocache` module instead. See [#215](https://github.com/helmetjs/helmet/issues/215)
+
+## 3.21.3 - 2020-02-24
+
+### Changed
+
+- Updated `helmet-csp` to v2.9.5
+ - Updated `bowser` subdependency from 2.7.0 to 2.9.0
+ - Fixed an issue some people were having when importing the `bowser` subdependency. See [helmet-csp#96](https://github.com/helmetjs/csp/issues/96) and [#101](https://github.com/helmetjs/csp/pull/101)
+
+## 3.21.2 - 2019-10-21
+
+### Changed
+
+- Updated `helmet-csp` to v2.9.4
+ - Updated `bowser` subdependency from 2.6.1 to 2.7.0. See [helmet-csp#94](https://github.com/helmetjs/csp/pull/94)
+
+## 3.21.1 - 2019-09-20
+
+### Fixed
+
+- Updated `helmet-csp` to v2.9.2
+ - Fixed a bug where a request from Firefox 4 could delete `default-src` from future responses
+ - Fixed tablet PC detection by updating `bowser` subdependency to latest version
+
+## 3.21.0 - 2019-09-04
+
+### Added
+
+- Updated `x-xss-protection` to v1.3.0
+ - Added `mode: null` to disable `mode=block`
+
+### Changed
+
+- Updated `helmet-csp` to v2.9.1
+ - Updated `bowser` subdependency from 2.5.3 to 2.5.4. See [helmet-csp#88](https://github.com/helmetjs/csp/pull/88)
+
+## 3.20.1 - 2019-08-28
+
+### Changed
+
+- Updated `helmet-csp` to v2.9.0
+
+## 3.20.0 - 2019-07-24
+
+### Changed
+
+- Updated `helmet-csp` to v2.8.0
+
+## 3.19.0 - 2019-07-17
+
+### Changed
+
+- Updated `dns-prefetch-control` to v0.2.0
+- Updated `dont-sniff-mimetype` to v1.1.0
+- Updated `helmet-crossdomain` to v0.4.0
+- Updated `hide-powered-by` to v1.1.0
+- Updated `x-xss-protection` to v1.2.0
+
+## 3.18.0 - 2019-05-05
+
+### Added
+
+- `featurePolicy` has 19 new features: `ambientLightSensor`, `documentDomain`, `documentWrite`, `encryptedMedia`, `fontDisplayLateSwap`, `layoutAnimations`, `legacyImageFormats`, `loadingFrameDefaultEager`, `oversizedImages`, `pictureInPicture`, `serial`, `syncScript`, `unoptimizedImages`, `unoptimizedLosslessImages`, `unoptimizedLossyImages`, `unsizedMedia`, `verticalScroll`, `wakeLock`, and `xr`
+
+### Changed
+
+- Updated `expect-ct` to v0.2.0
+- Updated `feature-policy` to v0.3.0
+- Updated `frameguard` to v3.1.0
+- Updated `nocache` to v2.1.0
+
+## 3.17.0 - 2019-05-03
+
+### Added
+
+- `referrerPolicy` now supports multiple values
+
+### Changed
+
+- Updated `referrerPolicy` to v1.2.0
+
+## 3.16.0 - 2019-03-10
+
+### Added
+
+- Add email to `bugs` field in `package.json`
+
+### Changed
+
+- Updated `hsts` to v2.2.0
+- Updated `ienoopen` to v1.1.0
+- Changelog is now in the [Keep A Changelog](https://keepachangelog.com/) format
+- Dropped support for Node <4. See [the commit](https://github.com/helmetjs/helmet/commit/a49cec3ca58cce484d2d05e1f908549caa92ed03) for more information
+- Updated Adam Baldwin's contact information
+
+### Deprecated
+
+- `helmet.hsts`'s `setIf` option has been deprecated and will be removed in `hsts@3`. See [helmetjs/hsts#22](https://github.com/helmetjs/hsts/issues/22) for more
+
+* The `includeSubdomains` option (with a lowercase `d`) has been deprecated and will be removed in `hsts@3`. Use the uppercase-D `includeSubDomains` option instead. See [helmetjs/hsts#21](https://github.com/helmetjs/hsts/issues/21) for more
+
+## 3.15.1 - 2019-02-10
+
+### Deprecated
+
+- The `hpkp` middleware has been deprecated. If you still need to use this module, install the standalone `hpkp` module from npm. See [#180](https://github.com/helmetjs/helmet/issues/180) for more.
+
+## 3.15.0 - 2018-11-07
+
+### Added
+
+- `helmet.featurePolicy` now supports four new features
+
+## 3.14.0 - 2018-10-09
+
+### Added
+
+- `helmet.featurePolicy` middleware
+
+## 3.13.0 - 2018-07-22
+
+### Added
+
+- `helmet.permittedCrossDomainPolicies` middleware
+
+## 3.12.2 - 2018-07-20
+
+### Fixed
+
+- Removed `lodash.reduce` dependency from `csp`
+
+## 3.12.1 - 2018-05-16
+
+### Fixed
+
+- `expectCt` should use comma instead of semicolon as delimiter
+
+## 3.12.0 - 2018-03-02
+
+### Added
+
+- `xssFilter` now supports `reportUri` option
+
+## 3.11.0 - 2018-02-09
+
+### Added
+
+- Main Helmet middleware is now named to help with debugging
+
+## 3.10.0 - 2018-01-23
+
+### Added
+
+- `csp` now supports `prefix-src` directive
+
+### Fixed
+
+- `csp` no longer loads JSON files internally, helping some module bundlers
+- `false` should be able to disable a CSP directive
+
+## 3.9.0 - 2017-10-13
+
+### Added
+
+- `csp` now supports `strict-dynamic` value
+- `csp` now supports `require-sri-for` directive
+
+### Changed
+
+- Removed `connect` dependency
+
+## 3.8.2 - 2017-09-27
+
+### Changed
+
+- Updated `connect` dependency to latest
+
+## 3.8.1 - 2017-07-28
+
+### Fixed
+
+- `csp` does not automatically set `report-to` when setting `report-uri`
+
+## 3.8.0 - 2017-07-21
+
+### Changed
+
+- `hsts` no longer cares whether it's HTTPS and always sets the header
+
+## 3.7.0 - 2017-07-21
+
+### Added
+
+- `csp` now supports `report-to` directive
+
+### Changed
+
+- Throw an error when used incorrectly
+- Add a few documentation files to `npmignore`
+
+## 3.6.1 - 2017-05-21
+
+### Changed
+
+- Bump `connect` version
+
+## 3.6.0 - 2017-05-04
+
+### Added
+
+- `expectCt` middleware for setting the `Expect-CT` header
+
+## 3.5.0 - 2017-03-06
+
+### Added
+
+- `csp` now supports the `worker-src` directive
+
+## 3.4.1 - 2017-02-24
+
+### Changed
+
+- Bump `connect` version
+
+## 3.4.0 - 2017-01-13
+
+### Added
+
+- `csp` now supports more `sandbox` directives
+
+## 3.3.0 - 2016-12-31
+
+### Added
+
+- `referrerPolicy` allows `strict-origin` and `strict-origin-when-cross-origin` directives
+
+### Changed
+
+- Bump `connect` version
+
+## 3.2.0 - 2016-12-22
+
+### Added
+
+- `csp` now allows `manifest-src` directive
+
+## 3.1.0 - 2016-11-03
+
+### Added
+
+- `csp` now allows `frame-src` directive
+
+## 3.0.0 - 2016-10-28
+
+### Changed
+
+- `csp` will check your directives for common mistakes and throw errors if it finds them. This can be disabled with `loose: true`.
+- Empty arrays are no longer allowed in `csp`. For source lists (like `script-src` or `object-src`), use the standard `scriptSrc: ["'none'"]`. The `sandbox` directive can be `sandbox: true` to block everything.
+- `false` can disable a CSP directive. For example, `scriptSrc: false` is the same as not specifying it.
+- In CSP, `reportOnly: true` no longer requires a `report-uri` to be set.
+- `hsts`'s `maxAge` now defaults to 180 days (instead of 1 day)
+- `hsts`'s `maxAge` parameter is seconds, not milliseconds
+- `hsts` includes subdomains by default
+- `domain` parameter in `frameguard` cannot be empty
+
+### Removed
+
+- `noEtag` option no longer present in `noCache`
+- iOS Chrome `connect-src` workaround in CSP module
+
+## 2.3.0 - 2016-09-30
+
+### Added
+
+- `hpkp` middleware now supports the `includeSubDomains` property with a capital D
+
+### Fixed
+
+- `hpkp` was setting `includeSubdomains` instead of `includeSubDomains`
+
+## 2.2.0 - 2016-09-16
+
+### Added
+
+- `referrerPolicy` middleware
+
+## 2.1.3 - 2016-09-07
+
+### Changed
+
+- Top-level aliases (like `helmet.xssFilter`) are no longer dynamically required
+
+## 2.1.2 - 2016-07-27
+
+### Deprecated
+
+- `nocache`'s `noEtag` option is now deprecated
+
+### Fixed
+
+- `csp` now better handles Firefox on mobile
+
+## 2.1.1 - 2016-06-10
+
+### Changed
+
+- Remove several dependencies from `helmet-csp`
+
+### Fixed
+
+- `frameguard` had a documentation error about its default value
+- `frameguard` docs in main Helmet readme said `frameguard`, not `helmet.frameguard`
+
+## 2.1.0 - 2016-05-18
+
+### Added
+
+- `csp` lets you dynamically set `reportOnly`
+
+## 2.0.0 - 2016-04-29
+
+### Added
+
+- Pass configuration to enable/disable default middlewares
+
+### Changed
+
+- `dnsPrefetchControl` middleware is now enabled by default
+
+### Removed
+
+- No more module aliases. There is now just one way to include each middleware
+- `frameguard` can no longer be initialized with strings; you must use an object
+
+### Fixed
+
+- Make `hpkp` lowercase in documentation
+- Update `hpkp` spec URL in readmes
+- Update `frameguard` header name in readme
+
+## 1.3.0 - 2016-03-01
+
+### Added
+
+- `hpkp` has a `setIf` option to conditionally set the header
+
+## 1.2.0 - 2016-02-29
+
+### Added
+
+- `csp` now has a `browserSniff` option to disable all user-agent sniffing
+
+### Changed
+
+- `frameguard` can now be initialized with options
+- Add `npmignore` file to speed up installs slightly
+
+## 1.1.0 - 2016-01-12
+
+### Added
+
+- Code of conduct
+- `dnsPrefetchControl` middleware
+
+### Fixed
+
+- `csp` readme had syntax errors
+
+## 1.0.2 - 2016-01-08
+
+### Fixed
+
+- `csp` wouldn't recognize `IE Mobile` browsers
+- `csp` had some errors in its readme
+- Main readme had a syntax error
+
+## 1.0.1 - 2015-12-19
+
+### Fixed
+
+- `csp` with no User Agent would cause errors
+
+## 1.0.0 - 2015-12-18
+
+### Added
+
+- `csp` module supports dynamically-generated values
+
+### Changed
+
+- `csp` directives are now under the `directives` key
+- `hpkp`'s `Report-Only` header is now opt-in, not opt-out
+- Tweak readmes of every sub-repo
+
+### Removed
+
+- `crossdomain` middleware
+- `csp` no longer throws errors when some directives aren't quoted (`'self'`, for example)
+- `maxage` option in the `hpkp` middleware
+- `safari5` option from `csp` module
+
+### Fixed
+
+- Old Firefox Content-Security-Policy behavior for `unsafe-inline` and `unsafe-eval`
+- Dynamic `csp` policies is no longer recursive
+
+## 0.15.0 - 2015-11-26
+
+### Changed
+
+- `hpkp` allows a `report-uri` without the `Report-Only` header
+
+## 0.14.0 - 2015-11-01
+
+### Added
+
+- `nocache` now sends the `Surrogate-Control` header
+
+### Changed
+
+- `nocache` no longer contains the `private` directive in the `Cache-Control` header
+
+## 0.13.0 - 2015-10-23
+
+### Added
+
+- `xssFilter` now has a function name
+- Added new CSP docs to readme
+
+### Changed
+
+- HSTS option renamed from `includeSubdomains` to `includeSubDomains`
+
+## 0.11.0 - 2015-09-18
+
+### Added
+
+- `csp` now supports Microsoft Edge
+- CSP Level 2 support
+
+### Changed
+
+- Updated `connect` to 3.4.0
+- Updated `depd` to 1.1.0
+
+### Fixed
+
+- Added `license` key to `csp`'s `package.json`
+- Empty `csp` directives now support every directive, not just `sandbox`
+
+## 0.10.0 - 2015-07-08
+
+### Added
+
+- Add "Handling CSP violations" to `csp` readme
+- Add license to `package.json`
+
+### Changed
+
+- `hpkp` had a link to the wrong place in its readme
+- `hpkp` requires 2 or more pins
+
+### Fixed
+
+- `hpkp` might have miscalculated `maxAge` slightly wrong
+
+## 0.9.0 - 2015-04-24
+
+### Changed
+
+- `nocache` adds `private` to its `Cache-Control` directive
+- Added a description to `package.json`
+
+## 0.8.0 - 2015-04-21
+
+### Changed
+
+- Removed hefty Lodash dependency from HSTS and CSP
+- Updated string detection module in Frameguard
+- Changed readme slightly to better reflect project's focus
+
+### Deprecated
+
+- Deprecated `crossdomain` middleware
+
+### Removed
+
+- `crossdomain` is no longer a default middleware
+
+## 0.7.1 - 2015-03-23
+
+### Changed
+
+- Updated all outdated dependencies (insofar as possible)
+- HSTS now uses Lodash like all the rest of the libraries
+
+## 0.7.0 - 2015-03-05
+
+### Added
+
+- `hpkp` middleware
+
+### Changed
+
+- Travis CI should test 0.10 and 0.12
+- Minor code cleanup
+
+## 0.6.2 - 2015-03-01
+
+### Changed
+
+- Improved `xssFilter` performance
+- Updated Lodash versions
+
+## 0.6.1 - 2015-02-13
+
+### Added
+
+- "Other recommended modules" in README
+
+### Changed
+
+- Updated Lodash version
+
+### Fixed
+
+- `frameguard` middleware exported a function called `xframe`
+
+## 0.6.0 - 2015-01-21
+
+### Added
+
+- You can disable `csp` for Android
+
+### Fixed
+
+- `csp` on Chrome Mobile on Android and iOS
+
+## 0.5.4 - 2014-12-21
+
+### Changed
+
+- `nocache` should force revalidation
+
+## 0.5.3 - 2014-12-08
+
+### Changed
+
+- `platform` version in CSP and X-XSS-Protection
+
+### Fixed
+
+- Updated bad wording in frameguard docs
+
+## 0.5.2 - 2014-11-16
+
+### Changed
+
+- Updated Connect version
+
+### Fixed
+
+- Fixed minor `csp` bugfixes
+
+## 0.5.1 - 2014-11-09
+
+### Changed
+
+- Updated URLs in `package.json` for new URL
+
+### Fixed
+
+- CSP would set all headers forever after receiving an unknown user agent
+
+## 0.5.0 - 2014-10-28
+
+### Added
+
+- Most middlewares have some aliases now
+
+### Changed
+
+- `xframe` now called `frameguard` (though `xframe` still works)
+- `frameguard` chooses sameorigin by default
+- `frameguard` understands "SAME-ORIGIN" in addition to "SAMEORIGIN"
+- `nocache` removed from default middleware stack
+- Middleware split out into their own modules
+- Documentation
+- Updated supported Node version to at least 0.10.0
+- Bumped Connect version
+
+### Removed
+
+- Deprecation warnings
+
+### Fixed
+
+- Readme link was broken
+
+## 0.4.2 - 2014-10-16
+
+### Added
+
+- Support preload in HSTS header
+
+## 0.4.1 - 2014-08-24
+
+### Added
+
+- Use [helmet-crossdomain](https://github.com/helmetjs/crossdomain) to test the waters
+- 2 spaces instead of 4 throughout the code
+
+## 0.4.0 - 2014-07-17
+
+### Added
+
+- `nocache` now sets the Expires and Pragma headers
+- `nocache` now allows you to crush ETags
+
+### Changed
+
+- Improved the docs for nosniff
+- Reverted HSTS behavior of requiring a specified max-age
+
+### Fixed
+
+- Allow HSTS to have a max-age of 0
+
+## 0.3.2 - 2014-06-30
+
+### Added
+
+- All middleware functions are named
+- Throw error with non-positive HSTS max-age
+
+### Changed
+
+- Added semicolons in README
+- Make some Errors more specific
+
+### Removed
+
+- Removed all comment headers; refer to the readme
+
+### Fixed
+
+- `helmet()` was having issues
+- Fixed Syntax errors in README
+
+This changelog was created after the release of 0.3.1.
diff --git a/node_modules/helmet/LICENSE b/node_modules/helmet/LICENSE
new file mode 100644
index 00000000..2df8eee3
--- /dev/null
+++ b/node_modules/helmet/LICENSE
@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) 2012-2025 Evan Hahn, Adam Baldwin
+
+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/helmet/README.md b/node_modules/helmet/README.md
new file mode 100644
index 00000000..db428767
--- /dev/null
+++ b/node_modules/helmet/README.md
@@ -0,0 +1,702 @@
+# Helmet
+
+Help secure Express apps by setting HTTP response headers.
+
+```javascript
+import helmet from "helmet";
+
+const app = express();
+
+app.use(helmet());
+```
+
+Helmet sets the following headers by default:
+
+- [`Content-Security-Policy`](#content-security-policy): A powerful allow-list of what can happen on your page which mitigates many attacks
+- [`Cross-Origin-Opener-Policy`](#cross-origin-opener-policy): Helps process-isolate your page
+- [`Cross-Origin-Resource-Policy`](#cross-origin-resource-policy): Blocks others from loading your resources cross-origin
+- [`Origin-Agent-Cluster`](#origin-agent-cluster): Changes process isolation to be origin-based
+- [`Referrer-Policy`](#referrer-policy): Controls the [`Referer`][Referer] header
+- [`Strict-Transport-Security`](#strict-transport-security): Tells browsers to prefer HTTPS
+- [`X-Content-Type-Options`](#x-content-type-options): Avoids [MIME sniffing]
+- [`X-DNS-Prefetch-Control`](#x-dns-prefetch-control): Controls DNS prefetching
+- [`X-Download-Options`](#x-download-options): Forces downloads to be saved (Internet Explorer only)
+- [`X-Frame-Options`](#x-frame-options): Legacy header that mitigates [clickjacking] attacks
+- [`X-Permitted-Cross-Domain-Policies`](#x-permitted-cross-domain-policies): Controls cross-domain behavior for Adobe products, like Acrobat
+- [`X-Powered-By`](#x-powered-by): Info about the web server. Removed because it could be used in simple attacks
+- [`X-XSS-Protection`](#x-xss-protection): Legacy header that tries to mitigate [XSS attacks][XSS], but makes things worse, so Helmet disables it
+
+Each header can be configured. For example, here's how you configure the `Content-Security-Policy` header:
+
+```js
+// Configure the Content-Security-Policy header.
+app.use(
+ helmet({
+ contentSecurityPolicy: {
+ directives: {
+ "script-src": ["'self'", "example.com"],
+ },
+ },
+ }),
+);
+```
+
+Headers can also be disabled. For example, here's how you disable the `Content-Security-Policy` and `X-Download-Options` headers:
+
+```js
+// Disable the Content-Security-Policy and X-Download-Options headers
+app.use(
+ helmet({
+ contentSecurityPolicy: false,
+ xDownloadOptions: false,
+ }),
+);
+```
+
+## Reference
+
+
+Content-Security-Policy
+
+Default:
+
+```http
+Content-Security-Policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests
+```
+
+The `Content-Security-Policy` header mitigates a large number of attacks, such as [cross-site scripting][XSS]. See [MDN's introductory article on Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).
+
+This header is powerful but likely requires some configuration for your specific app.
+
+To configure this header, pass an object with a nested `directives` object. Each key is a directive name in camel case (such as `defaultSrc`) or kebab case (such as `default-src`). Each value is an array (or other iterable) of strings or functions for that directive. If a function appears in the array, it will be called with the request and response objects.
+
+```javascript
+// Sets all of the defaults, but overrides `script-src`
+// and disables the default `style-src`.
+app.use(
+ helmet({
+ contentSecurityPolicy: {
+ directives: {
+ "script-src": ["'self'", "example.com"],
+ "style-src": null,
+ },
+ },
+ }),
+);
+```
+
+```js
+// Sets the `script-src` directive to
+// "'self' 'nonce-e33cc...'"
+// (or similar)
+app.use((req, res, next) => {
+ res.locals.cspNonce = crypto.randomBytes(32).toString("hex");
+ next();
+});
+app.use(
+ helmet({
+ contentSecurityPolicy: {
+ directives: {
+ scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.cspNonce}'`],
+ },
+ },
+ }),
+);
+```
+
+These directives are merged into a default policy, which you can disable by setting `useDefaults` to `false`.
+
+```javascript
+// Sets "Content-Security-Policy: default-src 'self';
+// script-src 'self' example.com;object-src 'none';
+// upgrade-insecure-requests"
+app.use(
+ helmet({
+ contentSecurityPolicy: {
+ useDefaults: false,
+ directives: {
+ defaultSrc: ["'self'"],
+ scriptSrc: ["'self'", "example.com"],
+ objectSrc: ["'none'"],
+ upgradeInsecureRequests: [],
+ },
+ },
+ }),
+);
+```
+
+You can get the default directives object with `helmet.contentSecurityPolicy.getDefaultDirectives()`. Here is the default policy (formatted for readability):
+
+```
+default-src 'self';
+base-uri 'self';
+font-src 'self' https: data:;
+form-action 'self';
+frame-ancestors 'self';
+img-src 'self' data:;
+object-src 'none';
+script-src 'self';
+script-src-attr 'none';
+style-src 'self' https: 'unsafe-inline';
+upgrade-insecure-requests
+```
+
+The `default-src` directive can be explicitly disabled by setting its value to `helmet.contentSecurityPolicy.dangerouslyDisableDefaultSrc`, but this is not recommended.
+
+You can set the [`Content-Security-Policy-Report-Only`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only) instead:
+
+```javascript
+// Sets the Content-Security-Policy-Report-Only header
+app.use(
+ helmet({
+ contentSecurityPolicy: {
+ directives: {
+ /* ... */
+ },
+ reportOnly: true,
+ },
+ }),
+);
+```
+
+Helmet performs very little validation on your CSP. You should rely on CSP checkers like [CSP Evaluator](https://csp-evaluator.withgoogle.com/) instead.
+
+To disable the `Content-Security-Policy` header:
+
+```js
+app.use(
+ helmet({
+ contentSecurityPolicy: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.contentSecurityPolicy())`.
+
+
+
+
+Cross-Origin-Embedder-Policy
+
+This header is not set by default.
+
+The `Cross-Origin-Embedder-Policy` header helps control what resources can be loaded cross-origin. See [MDN's article on this header](https://developer.cdn.mozilla.net/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy) for more.
+
+```js
+// Helmet does not set Cross-Origin-Embedder-Policy
+// by default.
+app.use(helmet());
+
+// Sets "Cross-Origin-Embedder-Policy: require-corp"
+app.use(helmet({ crossOriginEmbedderPolicy: true }));
+
+// Sets "Cross-Origin-Embedder-Policy: credentialless"
+app.use(helmet({ crossOriginEmbedderPolicy: { policy: "credentialless" } }));
+```
+
+You can use this as standalone middleware with `app.use(helmet.crossOriginEmbedderPolicy())`.
+
+
+
+
+Cross-Origin-Opener-Policy
+
+Default:
+
+```http
+Cross-Origin-Opener-Policy: same-origin
+```
+
+The `Cross-Origin-Opener-Policy` header helps process-isolate your page. For more, see [MDN's article on this header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy).
+
+```js
+// Sets "Cross-Origin-Opener-Policy: same-origin"
+app.use(helmet());
+
+// Sets "Cross-Origin-Opener-Policy: same-origin-allow-popups"
+app.use(
+ helmet({
+ crossOriginOpenerPolicy: { policy: "same-origin-allow-popups" },
+ }),
+);
+```
+
+To disable the `Cross-Origin-Opener-Policy` header:
+
+```js
+app.use(
+ helmet({
+ crossOriginOpenerPolicy: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.crossOriginOpenerPolicy())`.
+
+
+
+
+Cross-Origin-Resource-Policy
+
+Default:
+
+```http
+Cross-Origin-Resource-Policy: same-origin
+```
+
+The `Cross-Origin-Resource-Policy` header blocks others from loading your resources cross-origin in some cases. For more, see ["Consider deploying Cross-Origin Resource Policy"](https://resourcepolicy.fyi/) and [MDN's article on this header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy).
+
+```js
+// Sets "Cross-Origin-Resource-Policy: same-origin"
+app.use(helmet());
+
+// Sets "Cross-Origin-Resource-Policy: same-site"
+app.use(helmet({ crossOriginResourcePolicy: { policy: "same-site" } }));
+```
+
+To disable the `Cross-Origin-Resource-Policy` header:
+
+```js
+app.use(
+ helmet({
+ crossOriginResourcePolicy: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.crossOriginResourcePolicy())`.
+
+
+
+
+Origin-Agent-Cluster
+
+Default:
+
+```http
+Origin-Agent-Cluster: ?1
+```
+
+The `Origin-Agent-Cluster` header provides a mechanism to allow web applications to isolate their origins from other processes. Read more about it [in the spec](https://whatpr.org/html/6214/origin.html#origin-keyed-agent-clusters).
+
+This header takes no options and is set by default.
+
+```js
+// Sets "Origin-Agent-Cluster: ?1"
+app.use(helmet());
+```
+
+To disable the `Origin-Agent-Cluster` header:
+
+```js
+app.use(
+ helmet({
+ originAgentCluster: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.originAgentCluster())`.
+
+
+
+
+Referrer-Policy
+
+Default:
+
+```http
+Referrer-Policy: no-referrer
+```
+
+The `Referrer-Policy` header which controls what information is set in [the `Referer` request header][Referer]. See ["Referer header: privacy and security concerns"](https://developer.mozilla.org/en-US/docs/Web/Security/Referer_header:_privacy_and_security_concerns) and [the header's documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy) on MDN for more.
+
+```js
+// Sets "Referrer-Policy: no-referrer"
+app.use(helmet());
+```
+
+`policy` is a string or array of strings representing the policy. If passed as an array, it will be joined with commas, which is useful when setting [a fallback policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy#Specifying_a_fallback_policy). It defaults to `no-referrer`.
+
+```js
+// Sets "Referrer-Policy: no-referrer"
+app.use(
+ helmet({
+ referrerPolicy: {
+ policy: "no-referrer",
+ },
+ }),
+);
+
+// Sets "Referrer-Policy: origin,unsafe-url"
+app.use(
+ helmet({
+ referrerPolicy: {
+ policy: ["origin", "unsafe-url"],
+ },
+ }),
+);
+```
+
+To disable the `Referrer-Policy` header:
+
+```js
+app.use(
+ helmet({
+ referrerPolicy: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.referrerPolicy())`.
+
+
+
+
+Strict-Transport-Security
+
+Default:
+
+```http
+Strict-Transport-Security: max-age=31536000; includeSubDomains
+```
+
+The `Strict-Transport-Security` header tells browsers to prefer HTTPS instead of insecure HTTP. See [the documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) for more.
+
+```js
+// Sets "Strict-Transport-Security: max-age=31536000; includeSubDomains"
+app.use(helmet());
+```
+
+`maxAge` is the number of seconds browsers should remember to prefer HTTPS. If passed a non-integer, the value is rounded down. It defaults to 365 days.
+
+`includeSubDomains` is a boolean which dictates whether to include the `includeSubDomains` directive, which makes this policy extend to subdomains. It defaults to `true`.
+
+`preload` is a boolean. If true, it adds the `preload` directive, expressing intent to add your HSTS policy to browsers. See [the "Preloading Strict Transport Security" section on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security#Preloading_Strict_Transport_Security) for more. It defaults to `false`.
+
+```js
+// Sets "Strict-Transport-Security: max-age=123456; includeSubDomains"
+app.use(
+ helmet({
+ strictTransportSecurity: {
+ maxAge: 123456,
+ },
+ }),
+);
+
+// Sets "Strict-Transport-Security: max-age=123456"
+app.use(
+ helmet({
+ strictTransportSecurity: {
+ maxAge: 123456,
+ includeSubDomains: false,
+ },
+ }),
+);
+
+// Sets "Strict-Transport-Security: max-age=123456; includeSubDomains; preload"
+app.use(
+ helmet({
+ strictTransportSecurity: {
+ maxAge: 63072000,
+ preload: true,
+ },
+ }),
+);
+```
+
+To disable the `Strict-Transport-Security` header:
+
+```js
+app.use(
+ helmet({
+ strictTransportSecurity: false,
+ }),
+);
+```
+
+You may wish to disable this header for local development, as it can make your browser force redirects from `http://localhost` to `https://localhost`, which may not be desirable if you develop multiple apps using `localhost`. See [this issue](https://github.com/helmetjs/helmet/issues/451) for more discussion.
+
+You can use this as standalone middleware with `app.use(helmet.strictTransportSecurity())`.
+
+
+
+
+X-Content-Type-Options
+
+Default:
+
+```http
+X-Content-Type-Options: nosniff
+```
+
+The `X-Content-Type-Options` mitigates [MIME type sniffing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#MIME_sniffing) which can cause security issues. See [documentation for this header on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options) for more.
+
+This header takes no options and is set by default.
+
+```js
+// Sets "X-Content-Type-Options: nosniff"
+app.use(helmet());
+```
+
+To disable the `X-Content-Type-Options` header:
+
+```js
+app.use(
+ helmet({
+ xContentTypeOptions: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.xContentTypeOptions())`.
+
+
+
+
+X-DNS-Prefetch-Control
+
+Default:
+
+```http
+X-DNS-Prefetch-Control: off
+```
+
+The `X-DNS-Prefetch-Control` header helps control DNS prefetching, which can improve user privacy at the expense of performance. See [documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control) for more.
+
+```js
+// Sets "X-DNS-Prefetch-Control: off"
+app.use(helmet());
+```
+
+`allow` is a boolean dictating whether to enable DNS prefetching. It defaults to `false`.
+
+Examples:
+
+```js
+// Sets "X-DNS-Prefetch-Control: off"
+app.use(
+ helmet({
+ xDnsPrefetchControl: { allow: false },
+ }),
+);
+
+// Sets "X-DNS-Prefetch-Control: on"
+app.use(
+ helmet({
+ xDnsPrefetchControl: { allow: true },
+ }),
+);
+```
+
+To disable the `X-DNS-Prefetch-Control` header and use the browser's default value:
+
+```js
+app.use(
+ helmet({
+ xDnsPrefetchControl: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.xDnsPrefetchControl())`.
+
+
+
+
+X-Download-Options
+
+Default:
+
+```http
+X-Download-Options: noopen
+```
+
+The `X-Download-Options` header is specific to Internet Explorer 8. It forces potentially-unsafe downloads to be saved, mitigating execution of HTML in your site's context. For more, see [this old post on MSDN](https://docs.microsoft.com/en-us/archive/blogs/ie/ie8-security-part-v-comprehensive-protection).
+
+This header takes no options and is set by default.
+
+```js
+// Sets "X-Download-Options: noopen"
+app.use(helmet());
+```
+
+To disable the `X-Download-Options` header:
+
+```js
+app.use(
+ helmet({
+ xDownloadOptions: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.xDownloadOptions())`.
+
+
+
+
+X-Frame-Options
+
+Default:
+
+```http
+X-Frame-Options: SAMEORIGIN
+```
+
+The legacy `X-Frame-Options` header to help you mitigate [clickjacking attacks](https://en.wikipedia.org/wiki/Clickjacking). This header is superseded by [the `frame-ancestors` Content Security Policy directive](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors) but is still useful on old browsers or if no CSP is used. For more, see [the documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options).
+
+```js
+// Sets "X-Frame-Options: SAMEORIGIN"
+app.use(helmet());
+```
+
+`action` is a string that specifies which directive to useâeither `DENY` or `SAMEORIGIN`. (A legacy directive, `ALLOW-FROM`, is not supported by Helmet. [Read more here.](https://github.com/helmetjs/helmet/wiki/How-to-use-X%E2%80%93Frame%E2%80%93Options's-%60ALLOW%E2%80%93FROM%60-directive)) It defaults to `SAMEORIGIN`.
+
+Examples:
+
+```js
+// Sets "X-Frame-Options: DENY"
+app.use(
+ helmet({
+ xFrameOptions: { action: "deny" },
+ }),
+);
+
+// Sets "X-Frame-Options: SAMEORIGIN"
+app.use(
+ helmet({
+ xFrameOptions: { action: "sameorigin" },
+ }),
+);
+```
+
+To disable the `X-Frame-Options` header:
+
+```js
+app.use(
+ helmet({
+ xFrameOptions: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.xFrameOptions())`.
+
+
+
+
+X-Permitted-Cross-Domain-Policies
+
+Default:
+
+```http
+X-Permitted-Cross-Domain-Policies: none
+```
+
+The `X-Permitted-Cross-Domain-Policies` header tells some clients (mostly Adobe products) your domain's policy for loading cross-domain content. See [the description on OWASP](https://owasp.org/www-project-secure-headers/) for more.
+
+```js
+// Sets "X-Permitted-Cross-Domain-Policies: none"
+app.use(helmet());
+```
+
+`permittedPolicies` is a string that must be `"none"`, `"master-only"`, `"by-content-type"`, or `"all"`. It defaults to `"none"`.
+
+Examples:
+
+```js
+// Sets "X-Permitted-Cross-Domain-Policies: none"
+app.use(
+ helmet({
+ xPermittedCrossDomainPolicies: {
+ permittedPolicies: "none",
+ },
+ }),
+);
+
+// Sets "X-Permitted-Cross-Domain-Policies: by-content-type"
+app.use(
+ helmet({
+ xPermittedCrossDomainPolicies: {
+ permittedPolicies: "by-content-type",
+ },
+ }),
+);
+```
+
+To disable the `X-Permitted-Cross-Domain-Policies` header:
+
+```js
+app.use(
+ helmet({
+ xPermittedCrossDomainPolicies: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.xPermittedCrossDomainPolicies())`.
+
+
+
+
+X-Powered-By
+
+Default: the `X-Powered-By` header, if present, is removed.
+
+Helmet removes the `X-Powered-By` header, which is set by default in Express and some other frameworks. Removing the header offers very limited security benefits (see [this discussion](https://github.com/expressjs/express/pull/2813#issuecomment-159270428)) and is mostly removed to save bandwidth, but may thwart simplistic attackers.
+
+Note: [Express has a built-in way to disable the `X-Powered-By` header](https://stackoverflow.com/a/12484642/804100), which you may wish to use instead.
+
+The removal of this header takes no options. The header is removed by default.
+
+To disable this behavior:
+
+```js
+// Not required, but recommended for Express users:
+app.disable("x-powered-by");
+
+// Ask Helmet to ignore the X-Powered-By header.
+app.use(
+ helmet({
+ xPoweredBy: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.xPoweredBy())`.
+
+
+
+
+X-XSS-Protection
+
+Default:
+
+```http
+X-XSS-Protection: 0
+```
+
+Helmet disables browsers' buggy cross-site scripting filter by setting the legacy `X-XSS-Protection` header to `0`. See [discussion about disabling the header here](https://github.com/helmetjs/helmet/issues/230) and [documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection).
+
+This header takes no options and is set by default.
+
+To disable the `X-XSS-Protection` header:
+
+```js
+// This is not recommended.
+app.use(
+ helmet({
+ xXssProtection: false,
+ }),
+);
+```
+
+You can use this as standalone middleware with `app.use(helmet.xXssProtection())`.
+
+
+
+[Referer]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer
+[MIME sniffing]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#mime_sniffing
+[Clickjacking]: https://en.wikipedia.org/wiki/Clickjacking
+[XSS]: https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting
diff --git a/node_modules/helmet/SECURITY.md b/node_modules/helmet/SECURITY.md
new file mode 100644
index 00000000..406d4992
--- /dev/null
+++ b/node_modules/helmet/SECURITY.md
@@ -0,0 +1,7 @@
+# Security issue reporting & disclosure process
+
+If you feel you have found a security issue or concern with Helmet, please reach out to the maintainers.
+
+Contact Evan Hahn at or Adam Baldwin at . Evan Hahn [can also be reached in other ways](https://evanhahn.com/contact).
+
+We will try to communicate in a timely manner and address your concerns.
diff --git a/node_modules/helmet/index.cjs b/node_modules/helmet/index.cjs
new file mode 100644
index 00000000..7bff9fa4
--- /dev/null
+++ b/node_modules/helmet/index.cjs
@@ -0,0 +1,588 @@
+"use strict"
+
+Object.defineProperties(exports, {__esModule: {value: true}, [Symbol.toStringTag]: {value: "Module"}})
+
+const dangerouslyDisableDefaultSrc = Symbol("dangerouslyDisableDefaultSrc")
+const SHOULD_BE_QUOTED = new Set(["none", "self", "strict-dynamic", "report-sample", "inline-speculation-rules", "unsafe-inline", "unsafe-eval", "unsafe-hashes", "wasm-unsafe-eval"])
+const getDefaultDirectives = () => ({
+ "default-src": ["'self'"],
+ "base-uri": ["'self'"],
+ "font-src": ["'self'", "https:", "data:"],
+ "form-action": ["'self'"],
+ "frame-ancestors": ["'self'"],
+ "img-src": ["'self'", "data:"],
+ "object-src": ["'none'"],
+ "script-src": ["'self'"],
+ "script-src-attr": ["'none'"],
+ "style-src": ["'self'", "https:", "'unsafe-inline'"],
+ "upgrade-insecure-requests": []
+})
+const dashify = str => str.replace(/[A-Z]/g, capitalLetter => "-" + capitalLetter.toLowerCase())
+const assertDirectiveValueIsValid = (directiveName, directiveValue) => {
+ if (/;|,/.test(directiveValue)) {
+ throw new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`)
+ }
+}
+const assertDirectiveValueEntryIsValid = (directiveName, directiveValueEntry) => {
+ if (SHOULD_BE_QUOTED.has(directiveValueEntry) || directiveValueEntry.startsWith("nonce-") || directiveValueEntry.startsWith("sha256-") || directiveValueEntry.startsWith("sha384-") || directiveValueEntry.startsWith("sha512-")) {
+ throw new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}. ${JSON.stringify(directiveValueEntry)} should be quoted`)
+ }
+}
+function normalizeDirectives(options) {
+ const defaultDirectives = getDefaultDirectives()
+ const {useDefaults = true, directives: rawDirectives = defaultDirectives} = options
+ const result = new Map()
+ const directiveNamesSeen = new Set()
+ const directivesExplicitlyDisabled = new Set()
+ for (const rawDirectiveName in rawDirectives) {
+ if (!Object.hasOwn(rawDirectives, rawDirectiveName)) {
+ continue
+ }
+ if (rawDirectiveName.length === 0 || /[^a-zA-Z0-9-]/.test(rawDirectiveName)) {
+ throw new Error(`Content-Security-Policy received an invalid directive name ${JSON.stringify(rawDirectiveName)}`)
+ }
+ const directiveName = dashify(rawDirectiveName)
+ if (directiveNamesSeen.has(directiveName)) {
+ throw new Error(`Content-Security-Policy received a duplicate directive ${JSON.stringify(directiveName)}`)
+ }
+ directiveNamesSeen.add(directiveName)
+ const rawDirectiveValue = rawDirectives[rawDirectiveName]
+ let directiveValue
+ if (rawDirectiveValue === null) {
+ if (directiveName === "default-src") {
+ throw new Error("Content-Security-Policy needs a default-src but it was set to `null`. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.")
+ }
+ directivesExplicitlyDisabled.add(directiveName)
+ continue
+ } else if (typeof rawDirectiveValue === "string") {
+ directiveValue = [rawDirectiveValue]
+ } else if (!rawDirectiveValue) {
+ throw new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`)
+ } else if (rawDirectiveValue === dangerouslyDisableDefaultSrc) {
+ if (directiveName === "default-src") {
+ directivesExplicitlyDisabled.add("default-src")
+ continue
+ } else {
+ throw new Error(`Content-Security-Policy: tried to disable ${JSON.stringify(directiveName)} as if it were default-src; simply omit the key`)
+ }
+ } else {
+ directiveValue = rawDirectiveValue
+ }
+ for (const element of directiveValue) {
+ if (typeof element !== "string") continue
+ assertDirectiveValueIsValid(directiveName, element)
+ assertDirectiveValueEntryIsValid(directiveName, element)
+ }
+ result.set(directiveName, directiveValue)
+ }
+ if (useDefaults) {
+ Object.entries(defaultDirectives).forEach(([defaultDirectiveName, defaultDirectiveValue]) => {
+ if (!result.has(defaultDirectiveName) && !directivesExplicitlyDisabled.has(defaultDirectiveName)) {
+ result.set(defaultDirectiveName, defaultDirectiveValue)
+ }
+ })
+ }
+ if (!result.size) {
+ throw new Error("Content-Security-Policy has no directives. Either set some or disable the header")
+ }
+ if (!result.has("default-src") && !directivesExplicitlyDisabled.has("default-src")) {
+ throw new Error("Content-Security-Policy needs a default-src but none was provided. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.")
+ }
+ return result
+}
+function getHeaderValue(req, res, normalizedDirectives) {
+ const result = []
+ for (const [directiveName, rawDirectiveValue] of normalizedDirectives) {
+ let directiveValue = ""
+ for (const element of rawDirectiveValue) {
+ if (typeof element === "function") {
+ const newElement = element(req, res)
+ assertDirectiveValueEntryIsValid(directiveName, newElement)
+ directiveValue += " " + newElement
+ } else {
+ directiveValue += " " + element
+ }
+ }
+ if (directiveValue) {
+ assertDirectiveValueIsValid(directiveName, directiveValue)
+ result.push(`${directiveName}${directiveValue}`)
+ } else {
+ result.push(directiveName)
+ }
+ }
+ return result.join(";")
+}
+const contentSecurityPolicy = function contentSecurityPolicy(options = {}) {
+ const headerName = options.reportOnly ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy"
+ const normalizedDirectives = normalizeDirectives(options)
+ return function contentSecurityPolicyMiddleware(req, res, next) {
+ const result = getHeaderValue(req, res, normalizedDirectives)
+ if (result instanceof Error) {
+ next(result)
+ } else {
+ res.setHeader(headerName, result)
+ next()
+ }
+ }
+}
+contentSecurityPolicy.getDefaultDirectives = getDefaultDirectives
+contentSecurityPolicy.dangerouslyDisableDefaultSrc = dangerouslyDisableDefaultSrc
+
+const ALLOWED_POLICIES$2 = new Set(["require-corp", "credentialless", "unsafe-none"])
+function getHeaderValueFromOptions$6({policy = "require-corp"}) {
+ if (ALLOWED_POLICIES$2.has(policy)) {
+ return policy
+ } else {
+ throw new Error(`Cross-Origin-Embedder-Policy does not support the ${JSON.stringify(policy)} policy`)
+ }
+}
+function crossOriginEmbedderPolicy(options = {}) {
+ const headerValue = getHeaderValueFromOptions$6(options)
+ return function crossOriginEmbedderPolicyMiddleware(_req, res, next) {
+ res.setHeader("Cross-Origin-Embedder-Policy", headerValue)
+ next()
+ }
+}
+
+const ALLOWED_POLICIES$1 = new Set(["same-origin", "same-origin-allow-popups", "unsafe-none"])
+function getHeaderValueFromOptions$5({policy = "same-origin"}) {
+ if (ALLOWED_POLICIES$1.has(policy)) {
+ return policy
+ } else {
+ throw new Error(`Cross-Origin-Opener-Policy does not support the ${JSON.stringify(policy)} policy`)
+ }
+}
+function crossOriginOpenerPolicy(options = {}) {
+ const headerValue = getHeaderValueFromOptions$5(options)
+ return function crossOriginOpenerPolicyMiddleware(_req, res, next) {
+ res.setHeader("Cross-Origin-Opener-Policy", headerValue)
+ next()
+ }
+}
+
+const ALLOWED_POLICIES = new Set(["same-origin", "same-site", "cross-origin"])
+function getHeaderValueFromOptions$4({policy = "same-origin"}) {
+ if (ALLOWED_POLICIES.has(policy)) {
+ return policy
+ } else {
+ throw new Error(`Cross-Origin-Resource-Policy does not support the ${JSON.stringify(policy)} policy`)
+ }
+}
+function crossOriginResourcePolicy(options = {}) {
+ const headerValue = getHeaderValueFromOptions$4(options)
+ return function crossOriginResourcePolicyMiddleware(_req, res, next) {
+ res.setHeader("Cross-Origin-Resource-Policy", headerValue)
+ next()
+ }
+}
+
+function originAgentCluster() {
+ return function originAgentClusterMiddleware(_req, res, next) {
+ res.setHeader("Origin-Agent-Cluster", "?1")
+ next()
+ }
+}
+
+const ALLOWED_TOKENS = new Set(["no-referrer", "no-referrer-when-downgrade", "same-origin", "origin", "strict-origin", "origin-when-cross-origin", "strict-origin-when-cross-origin", "unsafe-url", ""])
+function getHeaderValueFromOptions$3({policy = ["no-referrer"]}) {
+ const tokens = typeof policy === "string" ? [policy] : policy
+ if (tokens.length === 0) {
+ throw new Error("Referrer-Policy received no policy tokens")
+ }
+ const tokensSeen = new Set()
+ tokens.forEach(token => {
+ if (!ALLOWED_TOKENS.has(token)) {
+ throw new Error(`Referrer-Policy received an unexpected policy token ${JSON.stringify(token)}`)
+ } else if (tokensSeen.has(token)) {
+ throw new Error(`Referrer-Policy received a duplicate policy token ${JSON.stringify(token)}`)
+ }
+ tokensSeen.add(token)
+ })
+ return tokens.join(",")
+}
+function referrerPolicy(options = {}) {
+ const headerValue = getHeaderValueFromOptions$3(options)
+ return function referrerPolicyMiddleware(_req, res, next) {
+ res.setHeader("Referrer-Policy", headerValue)
+ next()
+ }
+}
+
+const DEFAULT_MAX_AGE = 365 * 24 * 60 * 60
+function parseMaxAge(value = DEFAULT_MAX_AGE) {
+ if (value >= 0 && Number.isFinite(value)) {
+ return Math.floor(value)
+ } else {
+ throw new Error(`Strict-Transport-Security: ${JSON.stringify(value)} is not a valid value for maxAge. Please choose a positive integer.`)
+ }
+}
+function getHeaderValueFromOptions$2(options) {
+ if ("maxage" in options) {
+ throw new Error("Strict-Transport-Security received an unsupported property, `maxage`. Did you mean to pass `maxAge`?")
+ }
+ if ("includeSubdomains" in options) {
+ throw new Error('Strict-Transport-Security middleware should use `includeSubDomains` instead of `includeSubdomains`. (The correct one has an uppercase "D".)')
+ }
+ const directives = [`max-age=${parseMaxAge(options.maxAge)}`]
+ if (options.includeSubDomains === undefined || options.includeSubDomains) {
+ directives.push("includeSubDomains")
+ }
+ if (options.preload) {
+ directives.push("preload")
+ }
+ return directives.join("; ")
+}
+function strictTransportSecurity(options = {}) {
+ const headerValue = getHeaderValueFromOptions$2(options)
+ return function strictTransportSecurityMiddleware(_req, res, next) {
+ res.setHeader("Strict-Transport-Security", headerValue)
+ next()
+ }
+}
+
+function xContentTypeOptions() {
+ return function xContentTypeOptionsMiddleware(_req, res, next) {
+ res.setHeader("X-Content-Type-Options", "nosniff")
+ next()
+ }
+}
+
+function xDnsPrefetchControl(options = {}) {
+ const headerValue = options.allow ? "on" : "off"
+ return function xDnsPrefetchControlMiddleware(_req, res, next) {
+ res.setHeader("X-DNS-Prefetch-Control", headerValue)
+ next()
+ }
+}
+
+function xDownloadOptions() {
+ return function xDownloadOptionsMiddleware(_req, res, next) {
+ res.setHeader("X-Download-Options", "noopen")
+ next()
+ }
+}
+
+function getHeaderValueFromOptions$1({action = "sameorigin"}) {
+ const normalizedAction = typeof action === "string" ? action.toUpperCase() : action
+ switch (normalizedAction) {
+ case "SAME-ORIGIN":
+ return "SAMEORIGIN"
+ case "DENY":
+ case "SAMEORIGIN":
+ return normalizedAction
+ default:
+ throw new Error(`X-Frame-Options received an invalid action ${JSON.stringify(action)}`)
+ }
+}
+function xFrameOptions(options = {}) {
+ const headerValue = getHeaderValueFromOptions$1(options)
+ return function xFrameOptionsMiddleware(_req, res, next) {
+ res.setHeader("X-Frame-Options", headerValue)
+ next()
+ }
+}
+
+const ALLOWED_PERMITTED_POLICIES = new Set(["none", "master-only", "by-content-type", "all"])
+function getHeaderValueFromOptions({permittedPolicies = "none"}) {
+ if (ALLOWED_PERMITTED_POLICIES.has(permittedPolicies)) {
+ return permittedPolicies
+ } else {
+ throw new Error(`X-Permitted-Cross-Domain-Policies does not support ${JSON.stringify(permittedPolicies)}`)
+ }
+}
+function xPermittedCrossDomainPolicies(options = {}) {
+ const headerValue = getHeaderValueFromOptions(options)
+ return function xPermittedCrossDomainPoliciesMiddleware(_req, res, next) {
+ res.setHeader("X-Permitted-Cross-Domain-Policies", headerValue)
+ next()
+ }
+}
+
+function xPoweredBy() {
+ return function xPoweredByMiddleware(_req, res, next) {
+ res.removeHeader("X-Powered-By")
+ next()
+ }
+}
+
+function xXssProtection() {
+ return function xXssProtectionMiddleware(_req, res, next) {
+ res.setHeader("X-XSS-Protection", "0")
+ next()
+ }
+}
+
+function getMiddlewareFunctionsFromOptions(options) {
+ const result = []
+ switch (options.contentSecurityPolicy) {
+ case undefined:
+ case true:
+ result.push(contentSecurityPolicy())
+ break
+ case false:
+ break
+ default:
+ result.push(contentSecurityPolicy(options.contentSecurityPolicy))
+ break
+ }
+ switch (options.crossOriginEmbedderPolicy) {
+ case undefined:
+ case false:
+ break
+ case true:
+ result.push(crossOriginEmbedderPolicy())
+ break
+ default:
+ result.push(crossOriginEmbedderPolicy(options.crossOriginEmbedderPolicy))
+ break
+ }
+ switch (options.crossOriginOpenerPolicy) {
+ case undefined:
+ case true:
+ result.push(crossOriginOpenerPolicy())
+ break
+ case false:
+ break
+ default:
+ result.push(crossOriginOpenerPolicy(options.crossOriginOpenerPolicy))
+ break
+ }
+ switch (options.crossOriginResourcePolicy) {
+ case undefined:
+ case true:
+ result.push(crossOriginResourcePolicy())
+ break
+ case false:
+ break
+ default:
+ result.push(crossOriginResourcePolicy(options.crossOriginResourcePolicy))
+ break
+ }
+ switch (options.originAgentCluster) {
+ case undefined:
+ case true:
+ result.push(originAgentCluster())
+ break
+ case false:
+ break
+ default:
+ console.warn("Origin-Agent-Cluster does not take options. Remove the property to silence this warning.")
+ result.push(originAgentCluster())
+ break
+ }
+ switch (options.referrerPolicy) {
+ case undefined:
+ case true:
+ result.push(referrerPolicy())
+ break
+ case false:
+ break
+ default:
+ result.push(referrerPolicy(options.referrerPolicy))
+ break
+ }
+ if ("strictTransportSecurity" in options && "hsts" in options) {
+ throw new Error("Strict-Transport-Security option was specified twice. Remove `hsts` to silence this warning.")
+ }
+ const strictTransportSecurityOption = options.strictTransportSecurity ?? options.hsts
+ switch (strictTransportSecurityOption) {
+ case undefined:
+ case true:
+ result.push(strictTransportSecurity())
+ break
+ case false:
+ break
+ default:
+ result.push(strictTransportSecurity(strictTransportSecurityOption))
+ break
+ }
+ if ("xContentTypeOptions" in options && "noSniff" in options) {
+ throw new Error("X-Content-Type-Options option was specified twice. Remove `noSniff` to silence this warning.")
+ }
+ const xContentTypeOptionsOption = options.xContentTypeOptions ?? options.noSniff
+ switch (xContentTypeOptionsOption) {
+ case undefined:
+ case true:
+ result.push(xContentTypeOptions())
+ break
+ case false:
+ break
+ default:
+ console.warn("X-Content-Type-Options does not take options. Remove the property to silence this warning.")
+ result.push(xContentTypeOptions())
+ break
+ }
+ if ("xDnsPrefetchControl" in options && "dnsPrefetchControl" in options) {
+ throw new Error("X-DNS-Prefetch-Control option was specified twice. Remove `dnsPrefetchControl` to silence this warning.")
+ }
+ const xDnsPrefetchControlOption = options.xDnsPrefetchControl ?? options.dnsPrefetchControl
+ switch (xDnsPrefetchControlOption) {
+ case undefined:
+ case true:
+ result.push(xDnsPrefetchControl())
+ break
+ case false:
+ break
+ default:
+ result.push(xDnsPrefetchControl(xDnsPrefetchControlOption))
+ break
+ }
+ if ("xDownloadOptions" in options && "ieNoOpen" in options) {
+ throw new Error("X-Download-Options option was specified twice. Remove `ieNoOpen` to silence this warning.")
+ }
+ const xDownloadOptionsOption = options.xDownloadOptions ?? options.ieNoOpen
+ switch (xDownloadOptionsOption) {
+ case undefined:
+ case true:
+ result.push(xDownloadOptions())
+ break
+ case false:
+ break
+ default:
+ console.warn("X-Download-Options does not take options. Remove the property to silence this warning.")
+ result.push(xDownloadOptions())
+ break
+ }
+ if ("xFrameOptions" in options && "frameguard" in options) {
+ throw new Error("X-Frame-Options option was specified twice. Remove `frameguard` to silence this warning.")
+ }
+ const xFrameOptionsOption = options.xFrameOptions ?? options.frameguard
+ switch (xFrameOptionsOption) {
+ case undefined:
+ case true:
+ result.push(xFrameOptions())
+ break
+ case false:
+ break
+ default:
+ result.push(xFrameOptions(xFrameOptionsOption))
+ break
+ }
+ if ("xPermittedCrossDomainPolicies" in options && "permittedCrossDomainPolicies" in options) {
+ throw new Error("X-Permitted-Cross-Domain-Policies option was specified twice. Remove `permittedCrossDomainPolicies` to silence this warning.")
+ }
+ const xPermittedCrossDomainPoliciesOption = options.xPermittedCrossDomainPolicies ?? options.permittedCrossDomainPolicies
+ switch (xPermittedCrossDomainPoliciesOption) {
+ case undefined:
+ case true:
+ result.push(xPermittedCrossDomainPolicies())
+ break
+ case false:
+ break
+ default:
+ result.push(xPermittedCrossDomainPolicies(xPermittedCrossDomainPoliciesOption))
+ break
+ }
+ if ("xPoweredBy" in options && "hidePoweredBy" in options) {
+ throw new Error("X-Powered-By option was specified twice. Remove `hidePoweredBy` to silence this warning.")
+ }
+ const xPoweredByOption = options.xPoweredBy ?? options.hidePoweredBy
+ switch (xPoweredByOption) {
+ case undefined:
+ case true:
+ result.push(xPoweredBy())
+ break
+ case false:
+ break
+ default:
+ console.warn("X-Powered-By does not take options. Remove the property to silence this warning.")
+ result.push(xPoweredBy())
+ break
+ }
+ if ("xXssProtection" in options && "xssFilter" in options) {
+ throw new Error("X-XSS-Protection option was specified twice. Remove `xssFilter` to silence this warning.")
+ }
+ const xXssProtectionOption = options.xXssProtection ?? options.xssFilter
+ switch (xXssProtectionOption) {
+ case undefined:
+ case true:
+ result.push(xXssProtection())
+ break
+ case false:
+ break
+ default:
+ console.warn("X-XSS-Protection does not take options. Remove the property to silence this warning.")
+ result.push(xXssProtection())
+ break
+ }
+ return result
+}
+const helmet = Object.assign(
+ function helmet(options = {}) {
+ // People should be able to pass an options object with no prototype,
+ // so we want this optional chaining.
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (options.constructor?.name === "IncomingMessage") {
+ throw new Error("It appears you have done something like `app.use(helmet)`, but it should be `app.use(helmet())`.")
+ }
+ const middlewareFunctions = getMiddlewareFunctionsFromOptions(options)
+ return function helmetMiddleware(req, res, next) {
+ let middlewareIndex = 0
+ ;(function internalNext(err) {
+ if (err) {
+ next(err)
+ return
+ }
+ const middlewareFunction = middlewareFunctions[middlewareIndex]
+ if (middlewareFunction) {
+ middlewareIndex++
+ middlewareFunction(req, res, internalNext)
+ } else {
+ next()
+ }
+ })()
+ }
+ },
+ {
+ contentSecurityPolicy,
+ crossOriginEmbedderPolicy,
+ crossOriginOpenerPolicy,
+ crossOriginResourcePolicy,
+ originAgentCluster,
+ referrerPolicy,
+ strictTransportSecurity,
+ xContentTypeOptions,
+ xDnsPrefetchControl,
+ xDownloadOptions,
+ xFrameOptions,
+ xPermittedCrossDomainPolicies,
+ xPoweredBy,
+ xXssProtection,
+ // Legacy aliases
+ dnsPrefetchControl: xDnsPrefetchControl,
+ xssFilter: xXssProtection,
+ permittedCrossDomainPolicies: xPermittedCrossDomainPolicies,
+ ieNoOpen: xDownloadOptions,
+ noSniff: xContentTypeOptions,
+ frameguard: xFrameOptions,
+ hidePoweredBy: xPoweredBy,
+ hsts: strictTransportSecurity
+ }
+)
+
+exports.contentSecurityPolicy = contentSecurityPolicy
+exports.crossOriginEmbedderPolicy = crossOriginEmbedderPolicy
+exports.crossOriginOpenerPolicy = crossOriginOpenerPolicy
+exports.crossOriginResourcePolicy = crossOriginResourcePolicy
+exports.default = helmet
+exports.dnsPrefetchControl = xDnsPrefetchControl
+exports.frameguard = xFrameOptions
+exports.hidePoweredBy = xPoweredBy
+exports.hsts = strictTransportSecurity
+exports.ieNoOpen = xDownloadOptions
+exports.noSniff = xContentTypeOptions
+exports.originAgentCluster = originAgentCluster
+exports.permittedCrossDomainPolicies = xPermittedCrossDomainPolicies
+exports.referrerPolicy = referrerPolicy
+exports.strictTransportSecurity = strictTransportSecurity
+exports.xContentTypeOptions = xContentTypeOptions
+exports.xDnsPrefetchControl = xDnsPrefetchControl
+exports.xDownloadOptions = xDownloadOptions
+exports.xFrameOptions = xFrameOptions
+exports.xPermittedCrossDomainPolicies = xPermittedCrossDomainPolicies
+exports.xPoweredBy = xPoweredBy
+exports.xXssProtection = xXssProtection
+exports.xssFilter = xXssProtection
+
+module.exports = exports.default
+module.exports.default = module.exports
diff --git a/node_modules/helmet/index.d.cts b/node_modules/helmet/index.d.cts
new file mode 100644
index 00000000..2ad47b43
--- /dev/null
+++ b/node_modules/helmet/index.d.cts
@@ -0,0 +1,186 @@
+import {IncomingMessage, ServerResponse} from "node:http"
+
+type ContentSecurityPolicyDirectiveValueFunction = (req: IncomingMessage, res: ServerResponse) => string
+type ContentSecurityPolicyDirectiveValue = string | ContentSecurityPolicyDirectiveValueFunction
+interface ContentSecurityPolicyOptions {
+ useDefaults?: boolean
+ directives?: Record | typeof dangerouslyDisableDefaultSrc>
+ reportOnly?: boolean
+}
+interface ContentSecurityPolicy {
+ (options?: Readonly): (req: IncomingMessage, res: ServerResponse, next: (err?: Error) => void) => void
+ getDefaultDirectives: typeof getDefaultDirectives
+ dangerouslyDisableDefaultSrc: typeof dangerouslyDisableDefaultSrc
+}
+declare const dangerouslyDisableDefaultSrc: unique symbol
+declare const getDefaultDirectives: () => Record>
+declare const contentSecurityPolicy: ContentSecurityPolicy
+
+interface CrossOriginEmbedderPolicyOptions {
+ policy?: "require-corp" | "credentialless" | "unsafe-none"
+}
+declare function crossOriginEmbedderPolicy(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface CrossOriginOpenerPolicyOptions {
+ policy?: "same-origin" | "same-origin-allow-popups" | "unsafe-none"
+}
+declare function crossOriginOpenerPolicy(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface CrossOriginResourcePolicyOptions {
+ policy?: "same-origin" | "same-site" | "cross-origin"
+}
+declare function crossOriginResourcePolicy(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function originAgentCluster(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+type ReferrerPolicyToken = "no-referrer" | "no-referrer-when-downgrade" | "same-origin" | "origin" | "strict-origin" | "origin-when-cross-origin" | "strict-origin-when-cross-origin" | "unsafe-url" | ""
+interface ReferrerPolicyOptions {
+ policy?: ReferrerPolicyToken | ReferrerPolicyToken[]
+}
+declare function referrerPolicy(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface StrictTransportSecurityOptions {
+ maxAge?: number
+ includeSubDomains?: boolean
+ preload?: boolean
+}
+declare function strictTransportSecurity(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function xContentTypeOptions(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface XDnsPrefetchControlOptions {
+ allow?: boolean
+}
+declare function xDnsPrefetchControl(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function xDownloadOptions(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface XFrameOptionsOptions {
+ action?: "deny" | "sameorigin"
+}
+declare function xFrameOptions(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface XPermittedCrossDomainPoliciesOptions {
+ permittedPolicies?: "none" | "master-only" | "by-content-type" | "all"
+}
+declare function xPermittedCrossDomainPolicies(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function xPoweredBy(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function xXssProtection(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+type HelmetOptions = {
+ contentSecurityPolicy?: ContentSecurityPolicyOptions | boolean
+ crossOriginEmbedderPolicy?: CrossOriginEmbedderPolicyOptions | boolean
+ crossOriginOpenerPolicy?: CrossOriginOpenerPolicyOptions | boolean
+ crossOriginResourcePolicy?: CrossOriginResourcePolicyOptions | boolean
+ originAgentCluster?: boolean
+ referrerPolicy?: ReferrerPolicyOptions | boolean
+} & (
+ | {
+ strictTransportSecurity?: StrictTransportSecurityOptions | boolean
+ hsts?: never
+ }
+ | {
+ hsts?: StrictTransportSecurityOptions | boolean
+ strictTransportSecurity?: never
+ }
+) &
+ (
+ | {
+ xContentTypeOptions?: boolean
+ noSniff?: never
+ }
+ | {
+ noSniff?: boolean
+ xContentTypeOptions?: never
+ }
+ ) &
+ (
+ | {
+ xDnsPrefetchControl?: XDnsPrefetchControlOptions | boolean
+ dnsPrefetchControl?: never
+ }
+ | {
+ dnsPrefetchControl?: XDnsPrefetchControlOptions | boolean
+ xDnsPrefetchControl?: never
+ }
+ ) &
+ (
+ | {
+ xDownloadOptions?: boolean
+ ieNoOpen?: never
+ }
+ | {
+ ieNoOpen?: boolean
+ xDownloadOptions?: never
+ }
+ ) &
+ (
+ | {
+ xFrameOptions?: XFrameOptionsOptions | boolean
+ frameguard?: never
+ }
+ | {
+ frameguard?: XFrameOptionsOptions | boolean
+ xFrameOptions?: never
+ }
+ ) &
+ (
+ | {
+ xPermittedCrossDomainPolicies?: XPermittedCrossDomainPoliciesOptions | boolean
+ permittedCrossDomainPolicies?: never
+ }
+ | {
+ permittedCrossDomainPolicies?: XPermittedCrossDomainPoliciesOptions | boolean
+ xPermittedCrossDomainPolicies?: never
+ }
+ ) &
+ (
+ | {
+ xPoweredBy?: boolean
+ hidePoweredBy?: never
+ }
+ | {
+ hidePoweredBy?: boolean
+ xPoweredBy?: never
+ }
+ ) &
+ (
+ | {
+ xXssProtection?: boolean
+ xssFilter?: never
+ }
+ | {
+ xssFilter?: boolean
+ xXssProtection?: never
+ }
+ )
+interface Helmet {
+ (options?: Readonly): (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => void
+ contentSecurityPolicy: typeof contentSecurityPolicy
+ crossOriginEmbedderPolicy: typeof crossOriginEmbedderPolicy
+ crossOriginOpenerPolicy: typeof crossOriginOpenerPolicy
+ crossOriginResourcePolicy: typeof crossOriginResourcePolicy
+ originAgentCluster: typeof originAgentCluster
+ referrerPolicy: typeof referrerPolicy
+ strictTransportSecurity: typeof strictTransportSecurity
+ xContentTypeOptions: typeof xContentTypeOptions
+ xDnsPrefetchControl: typeof xDnsPrefetchControl
+ xDownloadOptions: typeof xDownloadOptions
+ xFrameOptions: typeof xFrameOptions
+ xPermittedCrossDomainPolicies: typeof xPermittedCrossDomainPolicies
+ xPoweredBy: typeof xPoweredBy
+ xXssProtection: typeof xXssProtection
+ dnsPrefetchControl: typeof xDnsPrefetchControl
+ frameguard: typeof xFrameOptions
+ hidePoweredBy: typeof xPoweredBy
+ hsts: typeof strictTransportSecurity
+ ieNoOpen: typeof xDownloadOptions
+ noSniff: typeof xContentTypeOptions
+ permittedCrossDomainPolicies: typeof xPermittedCrossDomainPolicies
+ xssFilter: typeof xXssProtection
+}
+declare const helmet: Helmet
+
+export {type HelmetOptions, contentSecurityPolicy, crossOriginEmbedderPolicy, crossOriginOpenerPolicy, crossOriginResourcePolicy, helmet as default, xDnsPrefetchControl as dnsPrefetchControl, xFrameOptions as frameguard, xPoweredBy as hidePoweredBy, strictTransportSecurity as hsts, xDownloadOptions as ieNoOpen, xContentTypeOptions as noSniff, originAgentCluster, xPermittedCrossDomainPolicies as permittedCrossDomainPolicies, referrerPolicy, strictTransportSecurity, xContentTypeOptions, xDnsPrefetchControl, xDownloadOptions, xFrameOptions, xPermittedCrossDomainPolicies, xPoweredBy, xXssProtection, xXssProtection as xssFilter}
diff --git a/node_modules/helmet/index.d.mts b/node_modules/helmet/index.d.mts
new file mode 100644
index 00000000..2ad47b43
--- /dev/null
+++ b/node_modules/helmet/index.d.mts
@@ -0,0 +1,186 @@
+import {IncomingMessage, ServerResponse} from "node:http"
+
+type ContentSecurityPolicyDirectiveValueFunction = (req: IncomingMessage, res: ServerResponse) => string
+type ContentSecurityPolicyDirectiveValue = string | ContentSecurityPolicyDirectiveValueFunction
+interface ContentSecurityPolicyOptions {
+ useDefaults?: boolean
+ directives?: Record | typeof dangerouslyDisableDefaultSrc>
+ reportOnly?: boolean
+}
+interface ContentSecurityPolicy {
+ (options?: Readonly): (req: IncomingMessage, res: ServerResponse, next: (err?: Error) => void) => void
+ getDefaultDirectives: typeof getDefaultDirectives
+ dangerouslyDisableDefaultSrc: typeof dangerouslyDisableDefaultSrc
+}
+declare const dangerouslyDisableDefaultSrc: unique symbol
+declare const getDefaultDirectives: () => Record>
+declare const contentSecurityPolicy: ContentSecurityPolicy
+
+interface CrossOriginEmbedderPolicyOptions {
+ policy?: "require-corp" | "credentialless" | "unsafe-none"
+}
+declare function crossOriginEmbedderPolicy(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface CrossOriginOpenerPolicyOptions {
+ policy?: "same-origin" | "same-origin-allow-popups" | "unsafe-none"
+}
+declare function crossOriginOpenerPolicy(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface CrossOriginResourcePolicyOptions {
+ policy?: "same-origin" | "same-site" | "cross-origin"
+}
+declare function crossOriginResourcePolicy(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function originAgentCluster(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+type ReferrerPolicyToken = "no-referrer" | "no-referrer-when-downgrade" | "same-origin" | "origin" | "strict-origin" | "origin-when-cross-origin" | "strict-origin-when-cross-origin" | "unsafe-url" | ""
+interface ReferrerPolicyOptions {
+ policy?: ReferrerPolicyToken | ReferrerPolicyToken[]
+}
+declare function referrerPolicy(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface StrictTransportSecurityOptions {
+ maxAge?: number
+ includeSubDomains?: boolean
+ preload?: boolean
+}
+declare function strictTransportSecurity(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function xContentTypeOptions(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface XDnsPrefetchControlOptions {
+ allow?: boolean
+}
+declare function xDnsPrefetchControl(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function xDownloadOptions(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface XFrameOptionsOptions {
+ action?: "deny" | "sameorigin"
+}
+declare function xFrameOptions(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+interface XPermittedCrossDomainPoliciesOptions {
+ permittedPolicies?: "none" | "master-only" | "by-content-type" | "all"
+}
+declare function xPermittedCrossDomainPolicies(options?: Readonly): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function xPoweredBy(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+declare function xXssProtection(): (_req: IncomingMessage, res: ServerResponse, next: () => void) => void
+
+type HelmetOptions = {
+ contentSecurityPolicy?: ContentSecurityPolicyOptions | boolean
+ crossOriginEmbedderPolicy?: CrossOriginEmbedderPolicyOptions | boolean
+ crossOriginOpenerPolicy?: CrossOriginOpenerPolicyOptions | boolean
+ crossOriginResourcePolicy?: CrossOriginResourcePolicyOptions | boolean
+ originAgentCluster?: boolean
+ referrerPolicy?: ReferrerPolicyOptions | boolean
+} & (
+ | {
+ strictTransportSecurity?: StrictTransportSecurityOptions | boolean
+ hsts?: never
+ }
+ | {
+ hsts?: StrictTransportSecurityOptions | boolean
+ strictTransportSecurity?: never
+ }
+) &
+ (
+ | {
+ xContentTypeOptions?: boolean
+ noSniff?: never
+ }
+ | {
+ noSniff?: boolean
+ xContentTypeOptions?: never
+ }
+ ) &
+ (
+ | {
+ xDnsPrefetchControl?: XDnsPrefetchControlOptions | boolean
+ dnsPrefetchControl?: never
+ }
+ | {
+ dnsPrefetchControl?: XDnsPrefetchControlOptions | boolean
+ xDnsPrefetchControl?: never
+ }
+ ) &
+ (
+ | {
+ xDownloadOptions?: boolean
+ ieNoOpen?: never
+ }
+ | {
+ ieNoOpen?: boolean
+ xDownloadOptions?: never
+ }
+ ) &
+ (
+ | {
+ xFrameOptions?: XFrameOptionsOptions | boolean
+ frameguard?: never
+ }
+ | {
+ frameguard?: XFrameOptionsOptions | boolean
+ xFrameOptions?: never
+ }
+ ) &
+ (
+ | {
+ xPermittedCrossDomainPolicies?: XPermittedCrossDomainPoliciesOptions | boolean
+ permittedCrossDomainPolicies?: never
+ }
+ | {
+ permittedCrossDomainPolicies?: XPermittedCrossDomainPoliciesOptions | boolean
+ xPermittedCrossDomainPolicies?: never
+ }
+ ) &
+ (
+ | {
+ xPoweredBy?: boolean
+ hidePoweredBy?: never
+ }
+ | {
+ hidePoweredBy?: boolean
+ xPoweredBy?: never
+ }
+ ) &
+ (
+ | {
+ xXssProtection?: boolean
+ xssFilter?: never
+ }
+ | {
+ xssFilter?: boolean
+ xXssProtection?: never
+ }
+ )
+interface Helmet {
+ (options?: Readonly): (req: IncomingMessage, res: ServerResponse, next: (err?: unknown) => void) => void
+ contentSecurityPolicy: typeof contentSecurityPolicy
+ crossOriginEmbedderPolicy: typeof crossOriginEmbedderPolicy
+ crossOriginOpenerPolicy: typeof crossOriginOpenerPolicy
+ crossOriginResourcePolicy: typeof crossOriginResourcePolicy
+ originAgentCluster: typeof originAgentCluster
+ referrerPolicy: typeof referrerPolicy
+ strictTransportSecurity: typeof strictTransportSecurity
+ xContentTypeOptions: typeof xContentTypeOptions
+ xDnsPrefetchControl: typeof xDnsPrefetchControl
+ xDownloadOptions: typeof xDownloadOptions
+ xFrameOptions: typeof xFrameOptions
+ xPermittedCrossDomainPolicies: typeof xPermittedCrossDomainPolicies
+ xPoweredBy: typeof xPoweredBy
+ xXssProtection: typeof xXssProtection
+ dnsPrefetchControl: typeof xDnsPrefetchControl
+ frameguard: typeof xFrameOptions
+ hidePoweredBy: typeof xPoweredBy
+ hsts: typeof strictTransportSecurity
+ ieNoOpen: typeof xDownloadOptions
+ noSniff: typeof xContentTypeOptions
+ permittedCrossDomainPolicies: typeof xPermittedCrossDomainPolicies
+ xssFilter: typeof xXssProtection
+}
+declare const helmet: Helmet
+
+export {type HelmetOptions, contentSecurityPolicy, crossOriginEmbedderPolicy, crossOriginOpenerPolicy, crossOriginResourcePolicy, helmet as default, xDnsPrefetchControl as dnsPrefetchControl, xFrameOptions as frameguard, xPoweredBy as hidePoweredBy, strictTransportSecurity as hsts, xDownloadOptions as ieNoOpen, xContentTypeOptions as noSniff, originAgentCluster, xPermittedCrossDomainPolicies as permittedCrossDomainPolicies, referrerPolicy, strictTransportSecurity, xContentTypeOptions, xDnsPrefetchControl, xDownloadOptions, xFrameOptions, xPermittedCrossDomainPolicies, xPoweredBy, xXssProtection, xXssProtection as xssFilter}
diff --git a/node_modules/helmet/index.mjs b/node_modules/helmet/index.mjs
new file mode 100644
index 00000000..0ff61008
--- /dev/null
+++ b/node_modules/helmet/index.mjs
@@ -0,0 +1,559 @@
+const dangerouslyDisableDefaultSrc = Symbol("dangerouslyDisableDefaultSrc")
+const SHOULD_BE_QUOTED = new Set(["none", "self", "strict-dynamic", "report-sample", "inline-speculation-rules", "unsafe-inline", "unsafe-eval", "unsafe-hashes", "wasm-unsafe-eval"])
+const getDefaultDirectives = () => ({
+ "default-src": ["'self'"],
+ "base-uri": ["'self'"],
+ "font-src": ["'self'", "https:", "data:"],
+ "form-action": ["'self'"],
+ "frame-ancestors": ["'self'"],
+ "img-src": ["'self'", "data:"],
+ "object-src": ["'none'"],
+ "script-src": ["'self'"],
+ "script-src-attr": ["'none'"],
+ "style-src": ["'self'", "https:", "'unsafe-inline'"],
+ "upgrade-insecure-requests": []
+})
+const dashify = str => str.replace(/[A-Z]/g, capitalLetter => "-" + capitalLetter.toLowerCase())
+const assertDirectiveValueIsValid = (directiveName, directiveValue) => {
+ if (/;|,/.test(directiveValue)) {
+ throw new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`)
+ }
+}
+const assertDirectiveValueEntryIsValid = (directiveName, directiveValueEntry) => {
+ if (SHOULD_BE_QUOTED.has(directiveValueEntry) || directiveValueEntry.startsWith("nonce-") || directiveValueEntry.startsWith("sha256-") || directiveValueEntry.startsWith("sha384-") || directiveValueEntry.startsWith("sha512-")) {
+ throw new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}. ${JSON.stringify(directiveValueEntry)} should be quoted`)
+ }
+}
+function normalizeDirectives(options) {
+ const defaultDirectives = getDefaultDirectives()
+ const {useDefaults = true, directives: rawDirectives = defaultDirectives} = options
+ const result = new Map()
+ const directiveNamesSeen = new Set()
+ const directivesExplicitlyDisabled = new Set()
+ for (const rawDirectiveName in rawDirectives) {
+ if (!Object.hasOwn(rawDirectives, rawDirectiveName)) {
+ continue
+ }
+ if (rawDirectiveName.length === 0 || /[^a-zA-Z0-9-]/.test(rawDirectiveName)) {
+ throw new Error(`Content-Security-Policy received an invalid directive name ${JSON.stringify(rawDirectiveName)}`)
+ }
+ const directiveName = dashify(rawDirectiveName)
+ if (directiveNamesSeen.has(directiveName)) {
+ throw new Error(`Content-Security-Policy received a duplicate directive ${JSON.stringify(directiveName)}`)
+ }
+ directiveNamesSeen.add(directiveName)
+ const rawDirectiveValue = rawDirectives[rawDirectiveName]
+ let directiveValue
+ if (rawDirectiveValue === null) {
+ if (directiveName === "default-src") {
+ throw new Error("Content-Security-Policy needs a default-src but it was set to `null`. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.")
+ }
+ directivesExplicitlyDisabled.add(directiveName)
+ continue
+ } else if (typeof rawDirectiveValue === "string") {
+ directiveValue = [rawDirectiveValue]
+ } else if (!rawDirectiveValue) {
+ throw new Error(`Content-Security-Policy received an invalid directive value for ${JSON.stringify(directiveName)}`)
+ } else if (rawDirectiveValue === dangerouslyDisableDefaultSrc) {
+ if (directiveName === "default-src") {
+ directivesExplicitlyDisabled.add("default-src")
+ continue
+ } else {
+ throw new Error(`Content-Security-Policy: tried to disable ${JSON.stringify(directiveName)} as if it were default-src; simply omit the key`)
+ }
+ } else {
+ directiveValue = rawDirectiveValue
+ }
+ for (const element of directiveValue) {
+ if (typeof element !== "string") continue
+ assertDirectiveValueIsValid(directiveName, element)
+ assertDirectiveValueEntryIsValid(directiveName, element)
+ }
+ result.set(directiveName, directiveValue)
+ }
+ if (useDefaults) {
+ Object.entries(defaultDirectives).forEach(([defaultDirectiveName, defaultDirectiveValue]) => {
+ if (!result.has(defaultDirectiveName) && !directivesExplicitlyDisabled.has(defaultDirectiveName)) {
+ result.set(defaultDirectiveName, defaultDirectiveValue)
+ }
+ })
+ }
+ if (!result.size) {
+ throw new Error("Content-Security-Policy has no directives. Either set some or disable the header")
+ }
+ if (!result.has("default-src") && !directivesExplicitlyDisabled.has("default-src")) {
+ throw new Error("Content-Security-Policy needs a default-src but none was provided. If you really want to disable it, set it to `contentSecurityPolicy.dangerouslyDisableDefaultSrc`.")
+ }
+ return result
+}
+function getHeaderValue(req, res, normalizedDirectives) {
+ const result = []
+ for (const [directiveName, rawDirectiveValue] of normalizedDirectives) {
+ let directiveValue = ""
+ for (const element of rawDirectiveValue) {
+ if (typeof element === "function") {
+ const newElement = element(req, res)
+ assertDirectiveValueEntryIsValid(directiveName, newElement)
+ directiveValue += " " + newElement
+ } else {
+ directiveValue += " " + element
+ }
+ }
+ if (directiveValue) {
+ assertDirectiveValueIsValid(directiveName, directiveValue)
+ result.push(`${directiveName}${directiveValue}`)
+ } else {
+ result.push(directiveName)
+ }
+ }
+ return result.join(";")
+}
+const contentSecurityPolicy = function contentSecurityPolicy(options = {}) {
+ const headerName = options.reportOnly ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy"
+ const normalizedDirectives = normalizeDirectives(options)
+ return function contentSecurityPolicyMiddleware(req, res, next) {
+ const result = getHeaderValue(req, res, normalizedDirectives)
+ if (result instanceof Error) {
+ next(result)
+ } else {
+ res.setHeader(headerName, result)
+ next()
+ }
+ }
+}
+contentSecurityPolicy.getDefaultDirectives = getDefaultDirectives
+contentSecurityPolicy.dangerouslyDisableDefaultSrc = dangerouslyDisableDefaultSrc
+
+const ALLOWED_POLICIES$2 = new Set(["require-corp", "credentialless", "unsafe-none"])
+function getHeaderValueFromOptions$6({policy = "require-corp"}) {
+ if (ALLOWED_POLICIES$2.has(policy)) {
+ return policy
+ } else {
+ throw new Error(`Cross-Origin-Embedder-Policy does not support the ${JSON.stringify(policy)} policy`)
+ }
+}
+function crossOriginEmbedderPolicy(options = {}) {
+ const headerValue = getHeaderValueFromOptions$6(options)
+ return function crossOriginEmbedderPolicyMiddleware(_req, res, next) {
+ res.setHeader("Cross-Origin-Embedder-Policy", headerValue)
+ next()
+ }
+}
+
+const ALLOWED_POLICIES$1 = new Set(["same-origin", "same-origin-allow-popups", "unsafe-none"])
+function getHeaderValueFromOptions$5({policy = "same-origin"}) {
+ if (ALLOWED_POLICIES$1.has(policy)) {
+ return policy
+ } else {
+ throw new Error(`Cross-Origin-Opener-Policy does not support the ${JSON.stringify(policy)} policy`)
+ }
+}
+function crossOriginOpenerPolicy(options = {}) {
+ const headerValue = getHeaderValueFromOptions$5(options)
+ return function crossOriginOpenerPolicyMiddleware(_req, res, next) {
+ res.setHeader("Cross-Origin-Opener-Policy", headerValue)
+ next()
+ }
+}
+
+const ALLOWED_POLICIES = new Set(["same-origin", "same-site", "cross-origin"])
+function getHeaderValueFromOptions$4({policy = "same-origin"}) {
+ if (ALLOWED_POLICIES.has(policy)) {
+ return policy
+ } else {
+ throw new Error(`Cross-Origin-Resource-Policy does not support the ${JSON.stringify(policy)} policy`)
+ }
+}
+function crossOriginResourcePolicy(options = {}) {
+ const headerValue = getHeaderValueFromOptions$4(options)
+ return function crossOriginResourcePolicyMiddleware(_req, res, next) {
+ res.setHeader("Cross-Origin-Resource-Policy", headerValue)
+ next()
+ }
+}
+
+function originAgentCluster() {
+ return function originAgentClusterMiddleware(_req, res, next) {
+ res.setHeader("Origin-Agent-Cluster", "?1")
+ next()
+ }
+}
+
+const ALLOWED_TOKENS = new Set(["no-referrer", "no-referrer-when-downgrade", "same-origin", "origin", "strict-origin", "origin-when-cross-origin", "strict-origin-when-cross-origin", "unsafe-url", ""])
+function getHeaderValueFromOptions$3({policy = ["no-referrer"]}) {
+ const tokens = typeof policy === "string" ? [policy] : policy
+ if (tokens.length === 0) {
+ throw new Error("Referrer-Policy received no policy tokens")
+ }
+ const tokensSeen = new Set()
+ tokens.forEach(token => {
+ if (!ALLOWED_TOKENS.has(token)) {
+ throw new Error(`Referrer-Policy received an unexpected policy token ${JSON.stringify(token)}`)
+ } else if (tokensSeen.has(token)) {
+ throw new Error(`Referrer-Policy received a duplicate policy token ${JSON.stringify(token)}`)
+ }
+ tokensSeen.add(token)
+ })
+ return tokens.join(",")
+}
+function referrerPolicy(options = {}) {
+ const headerValue = getHeaderValueFromOptions$3(options)
+ return function referrerPolicyMiddleware(_req, res, next) {
+ res.setHeader("Referrer-Policy", headerValue)
+ next()
+ }
+}
+
+const DEFAULT_MAX_AGE = 365 * 24 * 60 * 60
+function parseMaxAge(value = DEFAULT_MAX_AGE) {
+ if (value >= 0 && Number.isFinite(value)) {
+ return Math.floor(value)
+ } else {
+ throw new Error(`Strict-Transport-Security: ${JSON.stringify(value)} is not a valid value for maxAge. Please choose a positive integer.`)
+ }
+}
+function getHeaderValueFromOptions$2(options) {
+ if ("maxage" in options) {
+ throw new Error("Strict-Transport-Security received an unsupported property, `maxage`. Did you mean to pass `maxAge`?")
+ }
+ if ("includeSubdomains" in options) {
+ throw new Error('Strict-Transport-Security middleware should use `includeSubDomains` instead of `includeSubdomains`. (The correct one has an uppercase "D".)')
+ }
+ const directives = [`max-age=${parseMaxAge(options.maxAge)}`]
+ if (options.includeSubDomains === undefined || options.includeSubDomains) {
+ directives.push("includeSubDomains")
+ }
+ if (options.preload) {
+ directives.push("preload")
+ }
+ return directives.join("; ")
+}
+function strictTransportSecurity(options = {}) {
+ const headerValue = getHeaderValueFromOptions$2(options)
+ return function strictTransportSecurityMiddleware(_req, res, next) {
+ res.setHeader("Strict-Transport-Security", headerValue)
+ next()
+ }
+}
+
+function xContentTypeOptions() {
+ return function xContentTypeOptionsMiddleware(_req, res, next) {
+ res.setHeader("X-Content-Type-Options", "nosniff")
+ next()
+ }
+}
+
+function xDnsPrefetchControl(options = {}) {
+ const headerValue = options.allow ? "on" : "off"
+ return function xDnsPrefetchControlMiddleware(_req, res, next) {
+ res.setHeader("X-DNS-Prefetch-Control", headerValue)
+ next()
+ }
+}
+
+function xDownloadOptions() {
+ return function xDownloadOptionsMiddleware(_req, res, next) {
+ res.setHeader("X-Download-Options", "noopen")
+ next()
+ }
+}
+
+function getHeaderValueFromOptions$1({action = "sameorigin"}) {
+ const normalizedAction = typeof action === "string" ? action.toUpperCase() : action
+ switch (normalizedAction) {
+ case "SAME-ORIGIN":
+ return "SAMEORIGIN"
+ case "DENY":
+ case "SAMEORIGIN":
+ return normalizedAction
+ default:
+ throw new Error(`X-Frame-Options received an invalid action ${JSON.stringify(action)}`)
+ }
+}
+function xFrameOptions(options = {}) {
+ const headerValue = getHeaderValueFromOptions$1(options)
+ return function xFrameOptionsMiddleware(_req, res, next) {
+ res.setHeader("X-Frame-Options", headerValue)
+ next()
+ }
+}
+
+const ALLOWED_PERMITTED_POLICIES = new Set(["none", "master-only", "by-content-type", "all"])
+function getHeaderValueFromOptions({permittedPolicies = "none"}) {
+ if (ALLOWED_PERMITTED_POLICIES.has(permittedPolicies)) {
+ return permittedPolicies
+ } else {
+ throw new Error(`X-Permitted-Cross-Domain-Policies does not support ${JSON.stringify(permittedPolicies)}`)
+ }
+}
+function xPermittedCrossDomainPolicies(options = {}) {
+ const headerValue = getHeaderValueFromOptions(options)
+ return function xPermittedCrossDomainPoliciesMiddleware(_req, res, next) {
+ res.setHeader("X-Permitted-Cross-Domain-Policies", headerValue)
+ next()
+ }
+}
+
+function xPoweredBy() {
+ return function xPoweredByMiddleware(_req, res, next) {
+ res.removeHeader("X-Powered-By")
+ next()
+ }
+}
+
+function xXssProtection() {
+ return function xXssProtectionMiddleware(_req, res, next) {
+ res.setHeader("X-XSS-Protection", "0")
+ next()
+ }
+}
+
+function getMiddlewareFunctionsFromOptions(options) {
+ const result = []
+ switch (options.contentSecurityPolicy) {
+ case undefined:
+ case true:
+ result.push(contentSecurityPolicy())
+ break
+ case false:
+ break
+ default:
+ result.push(contentSecurityPolicy(options.contentSecurityPolicy))
+ break
+ }
+ switch (options.crossOriginEmbedderPolicy) {
+ case undefined:
+ case false:
+ break
+ case true:
+ result.push(crossOriginEmbedderPolicy())
+ break
+ default:
+ result.push(crossOriginEmbedderPolicy(options.crossOriginEmbedderPolicy))
+ break
+ }
+ switch (options.crossOriginOpenerPolicy) {
+ case undefined:
+ case true:
+ result.push(crossOriginOpenerPolicy())
+ break
+ case false:
+ break
+ default:
+ result.push(crossOriginOpenerPolicy(options.crossOriginOpenerPolicy))
+ break
+ }
+ switch (options.crossOriginResourcePolicy) {
+ case undefined:
+ case true:
+ result.push(crossOriginResourcePolicy())
+ break
+ case false:
+ break
+ default:
+ result.push(crossOriginResourcePolicy(options.crossOriginResourcePolicy))
+ break
+ }
+ switch (options.originAgentCluster) {
+ case undefined:
+ case true:
+ result.push(originAgentCluster())
+ break
+ case false:
+ break
+ default:
+ console.warn("Origin-Agent-Cluster does not take options. Remove the property to silence this warning.")
+ result.push(originAgentCluster())
+ break
+ }
+ switch (options.referrerPolicy) {
+ case undefined:
+ case true:
+ result.push(referrerPolicy())
+ break
+ case false:
+ break
+ default:
+ result.push(referrerPolicy(options.referrerPolicy))
+ break
+ }
+ if ("strictTransportSecurity" in options && "hsts" in options) {
+ throw new Error("Strict-Transport-Security option was specified twice. Remove `hsts` to silence this warning.")
+ }
+ const strictTransportSecurityOption = options.strictTransportSecurity ?? options.hsts
+ switch (strictTransportSecurityOption) {
+ case undefined:
+ case true:
+ result.push(strictTransportSecurity())
+ break
+ case false:
+ break
+ default:
+ result.push(strictTransportSecurity(strictTransportSecurityOption))
+ break
+ }
+ if ("xContentTypeOptions" in options && "noSniff" in options) {
+ throw new Error("X-Content-Type-Options option was specified twice. Remove `noSniff` to silence this warning.")
+ }
+ const xContentTypeOptionsOption = options.xContentTypeOptions ?? options.noSniff
+ switch (xContentTypeOptionsOption) {
+ case undefined:
+ case true:
+ result.push(xContentTypeOptions())
+ break
+ case false:
+ break
+ default:
+ console.warn("X-Content-Type-Options does not take options. Remove the property to silence this warning.")
+ result.push(xContentTypeOptions())
+ break
+ }
+ if ("xDnsPrefetchControl" in options && "dnsPrefetchControl" in options) {
+ throw new Error("X-DNS-Prefetch-Control option was specified twice. Remove `dnsPrefetchControl` to silence this warning.")
+ }
+ const xDnsPrefetchControlOption = options.xDnsPrefetchControl ?? options.dnsPrefetchControl
+ switch (xDnsPrefetchControlOption) {
+ case undefined:
+ case true:
+ result.push(xDnsPrefetchControl())
+ break
+ case false:
+ break
+ default:
+ result.push(xDnsPrefetchControl(xDnsPrefetchControlOption))
+ break
+ }
+ if ("xDownloadOptions" in options && "ieNoOpen" in options) {
+ throw new Error("X-Download-Options option was specified twice. Remove `ieNoOpen` to silence this warning.")
+ }
+ const xDownloadOptionsOption = options.xDownloadOptions ?? options.ieNoOpen
+ switch (xDownloadOptionsOption) {
+ case undefined:
+ case true:
+ result.push(xDownloadOptions())
+ break
+ case false:
+ break
+ default:
+ console.warn("X-Download-Options does not take options. Remove the property to silence this warning.")
+ result.push(xDownloadOptions())
+ break
+ }
+ if ("xFrameOptions" in options && "frameguard" in options) {
+ throw new Error("X-Frame-Options option was specified twice. Remove `frameguard` to silence this warning.")
+ }
+ const xFrameOptionsOption = options.xFrameOptions ?? options.frameguard
+ switch (xFrameOptionsOption) {
+ case undefined:
+ case true:
+ result.push(xFrameOptions())
+ break
+ case false:
+ break
+ default:
+ result.push(xFrameOptions(xFrameOptionsOption))
+ break
+ }
+ if ("xPermittedCrossDomainPolicies" in options && "permittedCrossDomainPolicies" in options) {
+ throw new Error("X-Permitted-Cross-Domain-Policies option was specified twice. Remove `permittedCrossDomainPolicies` to silence this warning.")
+ }
+ const xPermittedCrossDomainPoliciesOption = options.xPermittedCrossDomainPolicies ?? options.permittedCrossDomainPolicies
+ switch (xPermittedCrossDomainPoliciesOption) {
+ case undefined:
+ case true:
+ result.push(xPermittedCrossDomainPolicies())
+ break
+ case false:
+ break
+ default:
+ result.push(xPermittedCrossDomainPolicies(xPermittedCrossDomainPoliciesOption))
+ break
+ }
+ if ("xPoweredBy" in options && "hidePoweredBy" in options) {
+ throw new Error("X-Powered-By option was specified twice. Remove `hidePoweredBy` to silence this warning.")
+ }
+ const xPoweredByOption = options.xPoweredBy ?? options.hidePoweredBy
+ switch (xPoweredByOption) {
+ case undefined:
+ case true:
+ result.push(xPoweredBy())
+ break
+ case false:
+ break
+ default:
+ console.warn("X-Powered-By does not take options. Remove the property to silence this warning.")
+ result.push(xPoweredBy())
+ break
+ }
+ if ("xXssProtection" in options && "xssFilter" in options) {
+ throw new Error("X-XSS-Protection option was specified twice. Remove `xssFilter` to silence this warning.")
+ }
+ const xXssProtectionOption = options.xXssProtection ?? options.xssFilter
+ switch (xXssProtectionOption) {
+ case undefined:
+ case true:
+ result.push(xXssProtection())
+ break
+ case false:
+ break
+ default:
+ console.warn("X-XSS-Protection does not take options. Remove the property to silence this warning.")
+ result.push(xXssProtection())
+ break
+ }
+ return result
+}
+const helmet = Object.assign(
+ function helmet(options = {}) {
+ // People should be able to pass an options object with no prototype,
+ // so we want this optional chaining.
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (options.constructor?.name === "IncomingMessage") {
+ throw new Error("It appears you have done something like `app.use(helmet)`, but it should be `app.use(helmet())`.")
+ }
+ const middlewareFunctions = getMiddlewareFunctionsFromOptions(options)
+ return function helmetMiddleware(req, res, next) {
+ let middlewareIndex = 0
+ ;(function internalNext(err) {
+ if (err) {
+ next(err)
+ return
+ }
+ const middlewareFunction = middlewareFunctions[middlewareIndex]
+ if (middlewareFunction) {
+ middlewareIndex++
+ middlewareFunction(req, res, internalNext)
+ } else {
+ next()
+ }
+ })()
+ }
+ },
+ {
+ contentSecurityPolicy,
+ crossOriginEmbedderPolicy,
+ crossOriginOpenerPolicy,
+ crossOriginResourcePolicy,
+ originAgentCluster,
+ referrerPolicy,
+ strictTransportSecurity,
+ xContentTypeOptions,
+ xDnsPrefetchControl,
+ xDownloadOptions,
+ xFrameOptions,
+ xPermittedCrossDomainPolicies,
+ xPoweredBy,
+ xXssProtection,
+ // Legacy aliases
+ dnsPrefetchControl: xDnsPrefetchControl,
+ xssFilter: xXssProtection,
+ permittedCrossDomainPolicies: xPermittedCrossDomainPolicies,
+ ieNoOpen: xDownloadOptions,
+ noSniff: xContentTypeOptions,
+ frameguard: xFrameOptions,
+ hidePoweredBy: xPoweredBy,
+ hsts: strictTransportSecurity
+ }
+)
+
+export {contentSecurityPolicy, crossOriginEmbedderPolicy, crossOriginOpenerPolicy, crossOriginResourcePolicy, helmet as default, xDnsPrefetchControl as dnsPrefetchControl, xFrameOptions as frameguard, xPoweredBy as hidePoweredBy, strictTransportSecurity as hsts, xDownloadOptions as ieNoOpen, xContentTypeOptions as noSniff, originAgentCluster, xPermittedCrossDomainPolicies as permittedCrossDomainPolicies, referrerPolicy, strictTransportSecurity, xContentTypeOptions, xDnsPrefetchControl, xDownloadOptions, xFrameOptions, xPermittedCrossDomainPolicies, xPoweredBy, xXssProtection, xXssProtection as xssFilter}
diff --git a/node_modules/helmet/package.json b/node_modules/helmet/package.json
new file mode 100644
index 00000000..88688157
--- /dev/null
+++ b/node_modules/helmet/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "helmet",
+ "description": "help secure Express/Connect apps with various HTTP headers",
+ "version": "8.1.0",
+ "author": "Adam Baldwin (https://evilpacket.net)",
+ "contributors": [
+ "Evan Hahn (https://evanhahn.com)"
+ ],
+ "homepage": "https://helmetjs.github.io/",
+ "bugs": {
+ "url": "https://github.com/helmetjs/helmet/issues",
+ "email": "me@evanhahn.com"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/helmetjs/helmet.git"
+ },
+ "license": "MIT",
+ "keywords": [
+ "express",
+ "security",
+ "headers",
+ "backend",
+ "content-security-policy",
+ "cross-origin-embedder-policy",
+ "cross-origin-opener-policy",
+ "cross-origin-resource-policy",
+ "origin-agent-cluster",
+ "referrer-policy",
+ "strict-transport-security",
+ "x-content-type-options",
+ "x-dns-prefetch-control",
+ "x-download-options",
+ "x-frame-options",
+ "x-permitted-cross-domain-policies",
+ "x-powered-by",
+ "x-xss-protection"
+ ],
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "exports": {
+ "import": "./index.mjs",
+ "require": "./index.cjs"
+ },
+ "main": "./index.cjs",
+ "types": "./index.d.cts"
+}
diff --git a/node_modules/jsonwebtoken/LICENSE b/node_modules/jsonwebtoken/LICENSE
new file mode 100644
index 00000000..bcd1854c
--- /dev/null
+++ b/node_modules/jsonwebtoken/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Auth0, Inc. (http://auth0.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/jsonwebtoken/README.md b/node_modules/jsonwebtoken/README.md
new file mode 100644
index 00000000..4e20dd9c
--- /dev/null
+++ b/node_modules/jsonwebtoken/README.md
@@ -0,0 +1,396 @@
+# jsonwebtoken
+
+| **Build** | **Dependency** |
+|-----------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
+| [](http://travis-ci.org/auth0/node-jsonwebtoken) | [](https://david-dm.org/auth0/node-jsonwebtoken) |
+
+
+An implementation of [JSON Web Tokens](https://tools.ietf.org/html/rfc7519).
+
+This was developed against `draft-ietf-oauth-json-web-token-08`. It makes use of [node-jws](https://github.com/brianloveswords/node-jws)
+
+# Install
+
+```bash
+$ npm install jsonwebtoken
+```
+
+# Migration notes
+
+* [From v8 to v9](https://github.com/auth0/node-jsonwebtoken/wiki/Migration-Notes:-v8-to-v9)
+* [From v7 to v8](https://github.com/auth0/node-jsonwebtoken/wiki/Migration-Notes:-v7-to-v8)
+
+# Usage
+
+### jwt.sign(payload, secretOrPrivateKey, [options, callback])
+
+(Asynchronous) If a callback is supplied, the callback is called with the `err` or the JWT.
+
+(Synchronous) Returns the JsonWebToken as string
+
+`payload` could be an object literal, buffer or string representing valid JSON.
+> **Please _note_ that** `exp` or any other claim is only set if the payload is an object literal. Buffer or string payloads are not checked for JSON validity.
+
+> If `payload` is not a buffer or a string, it will be coerced into a string using `JSON.stringify`.
+
+`secretOrPrivateKey` is a string (utf-8 encoded), buffer, object, or KeyObject containing either the secret for HMAC algorithms or the PEM
+encoded private key for RSA and ECDSA. In case of a private key with passphrase an object `{ key, passphrase }` can be used (based on [crypto documentation](https://nodejs.org/api/crypto.html#crypto_sign_sign_private_key_output_format)), in this case be sure you pass the `algorithm` option.
+When signing with RSA algorithms the minimum modulus length is 2048 except when the allowInsecureKeySizes option is set to true. Private keys below this size will be rejected with an error.
+
+`options`:
+
+* `algorithm` (default: `HS256`)
+* `expiresIn`: expressed in seconds or a string describing a time span [vercel/ms](https://github.com/vercel/ms).
+ > Eg: `60`, `"2 days"`, `"10h"`, `"7d"`. A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default (`"120"` is equal to `"120ms"`).
+* `notBefore`: expressed in seconds or a string describing a time span [vercel/ms](https://github.com/vercel/ms).
+ > Eg: `60`, `"2 days"`, `"10h"`, `"7d"`. A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default (`"120"` is equal to `"120ms"`).
+* `audience`
+* `issuer`
+* `jwtid`
+* `subject`
+* `noTimestamp`
+* `header`
+* `keyid`
+* `mutatePayload`: if true, the sign function will modify the payload object directly. This is useful if you need a raw reference to the payload after claims have been applied to it but before it has been encoded into a token.
+* `allowInsecureKeySizes`: if true allows private keys with a modulus below 2048 to be used for RSA
+* `allowInvalidAsymmetricKeyTypes`: if true, allows asymmetric keys which do not match the specified algorithm. This option is intended only for backwards compatability and should be avoided.
+
+
+
+> There are no default values for `expiresIn`, `notBefore`, `audience`, `subject`, `issuer`. These claims can also be provided in the payload directly with `exp`, `nbf`, `aud`, `sub` and `iss` respectively, but you **_can't_** include in both places.
+
+Remember that `exp`, `nbf` and `iat` are **NumericDate**, see related [Token Expiration (exp claim)](#token-expiration-exp-claim)
+
+
+The header can be customized via the `options.header` object.
+
+Generated jwts will include an `iat` (issued at) claim by default unless `noTimestamp` is specified. If `iat` is inserted in the payload, it will be used instead of the real timestamp for calculating other things like `exp` given a timespan in `options.expiresIn`.
+
+Synchronous Sign with default (HMAC SHA256)
+
+```js
+var jwt = require('jsonwebtoken');
+var token = jwt.sign({ foo: 'bar' }, 'shhhhh');
+```
+
+Synchronous Sign with RSA SHA256
+```js
+// sign with RSA SHA256
+var privateKey = fs.readFileSync('private.key');
+var token = jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' });
+```
+
+Sign asynchronously
+```js
+jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' }, function(err, token) {
+ console.log(token);
+});
+```
+
+Backdate a jwt 30 seconds
+```js
+var older_token = jwt.sign({ foo: 'bar', iat: Math.floor(Date.now() / 1000) - 30 }, 'shhhhh');
+```
+
+#### Token Expiration (exp claim)
+
+The standard for JWT defines an `exp` claim for expiration. The expiration is represented as a **NumericDate**:
+
+> A JSON numeric value representing the number of seconds from 1970-01-01T00:00:00Z UTC until the specified UTC date/time, ignoring leap seconds. This is equivalent to the IEEE Std 1003.1, 2013 Edition [POSIX.1] definition "Seconds Since the Epoch", in which each day is accounted for by exactly 86400 seconds, other than that non-integer values can be represented. See RFC 3339 [RFC3339] for details regarding date/times in general and UTC in particular.
+
+This means that the `exp` field should contain the number of seconds since the epoch.
+
+Signing a token with 1 hour of expiration:
+
+```javascript
+jwt.sign({
+ exp: Math.floor(Date.now() / 1000) + (60 * 60),
+ data: 'foobar'
+}, 'secret');
+```
+
+Another way to generate a token like this with this library is:
+
+```javascript
+jwt.sign({
+ data: 'foobar'
+}, 'secret', { expiresIn: 60 * 60 });
+
+//or even better:
+
+jwt.sign({
+ data: 'foobar'
+}, 'secret', { expiresIn: '1h' });
+```
+
+### jwt.verify(token, secretOrPublicKey, [options, callback])
+
+(Asynchronous) If a callback is supplied, function acts asynchronously. The callback is called with the decoded payload if the signature is valid and optional expiration, audience, or issuer are valid. If not, it will be called with the error.
+
+(Synchronous) If a callback is not supplied, function acts synchronously. Returns the payload decoded if the signature is valid and optional expiration, audience, or issuer are valid. If not, it will throw the error.
+
+> __Warning:__ When the token comes from an untrusted source (e.g. user input or external requests), the returned decoded payload should be treated like any other user input; please make sure to sanitize and only work with properties that are expected
+
+`token` is the JsonWebToken string
+
+`secretOrPublicKey` is a string (utf-8 encoded), buffer, or KeyObject containing either the secret for HMAC algorithms, or the PEM
+encoded public key for RSA and ECDSA.
+If `jwt.verify` is called asynchronous, `secretOrPublicKey` can be a function that should fetch the secret or public key. See below for a detailed example
+
+As mentioned in [this comment](https://github.com/auth0/node-jsonwebtoken/issues/208#issuecomment-231861138), there are other libraries that expect base64 encoded secrets (random bytes encoded using base64), if that is your case you can pass `Buffer.from(secret, 'base64')`, by doing this the secret will be decoded using base64 and the token verification will use the original random bytes.
+
+`options`
+
+* `algorithms`: List of strings with the names of the allowed algorithms. For instance, `["HS256", "HS384"]`.
+ > If not specified a defaults will be used based on the type of key provided
+ > * secret - ['HS256', 'HS384', 'HS512']
+ > * rsa - ['RS256', 'RS384', 'RS512']
+ > * ec - ['ES256', 'ES384', 'ES512']
+ > * default - ['RS256', 'RS384', 'RS512']
+* `audience`: if you want to check audience (`aud`), provide a value here. The audience can be checked against a string, a regular expression or a list of strings and/or regular expressions.
+ > Eg: `"urn:foo"`, `/urn:f[o]{2}/`, `[/urn:f[o]{2}/, "urn:bar"]`
+* `complete`: return an object with the decoded `{ payload, header, signature }` instead of only the usual content of the payload.
+* `issuer` (optional): string or array of strings of valid values for the `iss` field.
+* `jwtid` (optional): if you want to check JWT ID (`jti`), provide a string value here.
+* `ignoreExpiration`: if `true` do not validate the expiration of the token.
+* `ignoreNotBefore`...
+* `subject`: if you want to check subject (`sub`), provide a value here
+* `clockTolerance`: number of seconds to tolerate when checking the `nbf` and `exp` claims, to deal with small clock differences among different servers
+* `maxAge`: the maximum allowed age for tokens to still be valid. It is expressed in seconds or a string describing a time span [vercel/ms](https://github.com/vercel/ms).
+ > Eg: `1000`, `"2 days"`, `"10h"`, `"7d"`. A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default (`"120"` is equal to `"120ms"`).
+* `clockTimestamp`: the time in seconds that should be used as the current time for all necessary comparisons.
+* `nonce`: if you want to check `nonce` claim, provide a string value here. It is used on Open ID for the ID Tokens. ([Open ID implementation notes](https://openid.net/specs/openid-connect-core-1_0.html#NonceNotes))
+* `allowInvalidAsymmetricKeyTypes`: if true, allows asymmetric keys which do not match the specified algorithm. This option is intended only for backwards compatability and should be avoided.
+
+```js
+// verify a token symmetric - synchronous
+var decoded = jwt.verify(token, 'shhhhh');
+console.log(decoded.foo) // bar
+
+// verify a token symmetric
+jwt.verify(token, 'shhhhh', function(err, decoded) {
+ console.log(decoded.foo) // bar
+});
+
+// invalid token - synchronous
+try {
+ var decoded = jwt.verify(token, 'wrong-secret');
+} catch(err) {
+ // err
+}
+
+// invalid token
+jwt.verify(token, 'wrong-secret', function(err, decoded) {
+ // err
+ // decoded undefined
+});
+
+// verify a token asymmetric
+var cert = fs.readFileSync('public.pem'); // get public key
+jwt.verify(token, cert, function(err, decoded) {
+ console.log(decoded.foo) // bar
+});
+
+// verify audience
+var cert = fs.readFileSync('public.pem'); // get public key
+jwt.verify(token, cert, { audience: 'urn:foo' }, function(err, decoded) {
+ // if audience mismatch, err == invalid audience
+});
+
+// verify issuer
+var cert = fs.readFileSync('public.pem'); // get public key
+jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer' }, function(err, decoded) {
+ // if issuer mismatch, err == invalid issuer
+});
+
+// verify jwt id
+var cert = fs.readFileSync('public.pem'); // get public key
+jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid' }, function(err, decoded) {
+ // if jwt id mismatch, err == invalid jwt id
+});
+
+// verify subject
+var cert = fs.readFileSync('public.pem'); // get public key
+jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid', subject: 'subject' }, function(err, decoded) {
+ // if subject mismatch, err == invalid subject
+});
+
+// alg mismatch
+var cert = fs.readFileSync('public.pem'); // get public key
+jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) {
+ // if token alg != RS256, err == invalid signature
+});
+
+// Verify using getKey callback
+// Example uses https://github.com/auth0/node-jwks-rsa as a way to fetch the keys.
+var jwksClient = require('jwks-rsa');
+var client = jwksClient({
+ jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json'
+});
+function getKey(header, callback){
+ client.getSigningKey(header.kid, function(err, key) {
+ var signingKey = key.publicKey || key.rsaPublicKey;
+ callback(null, signingKey);
+ });
+}
+
+jwt.verify(token, getKey, options, function(err, decoded) {
+ console.log(decoded.foo) // bar
+});
+
+```
+
+
+Need to peek into a JWT without verifying it? (Click to expand)
+
+### jwt.decode(token [, options])
+
+(Synchronous) Returns the decoded payload without verifying if the signature is valid.
+
+> __Warning:__ This will __not__ verify whether the signature is valid. You should __not__ use this for untrusted messages. You most likely want to use `jwt.verify` instead.
+
+> __Warning:__ When the token comes from an untrusted source (e.g. user input or external request), the returned decoded payload should be treated like any other user input; please make sure to sanitize and only work with properties that are expected
+
+
+`token` is the JsonWebToken string
+
+`options`:
+
+* `json`: force JSON.parse on the payload even if the header doesn't contain `"typ":"JWT"`.
+* `complete`: return an object with the decoded payload and header.
+
+Example
+
+```js
+// get the decoded payload ignoring signature, no secretOrPrivateKey needed
+var decoded = jwt.decode(token);
+
+// get the decoded payload and header
+var decoded = jwt.decode(token, {complete: true});
+console.log(decoded.header);
+console.log(decoded.payload)
+```
+
+
+
+## Errors & Codes
+Possible thrown errors during verification.
+Error is the first argument of the verification callback.
+
+### TokenExpiredError
+
+Thrown error if the token is expired.
+
+Error object:
+
+* name: 'TokenExpiredError'
+* message: 'jwt expired'
+* expiredAt: [ExpDate]
+
+```js
+jwt.verify(token, 'shhhhh', function(err, decoded) {
+ if (err) {
+ /*
+ err = {
+ name: 'TokenExpiredError',
+ message: 'jwt expired',
+ expiredAt: 1408621000
+ }
+ */
+ }
+});
+```
+
+### JsonWebTokenError
+Error object:
+
+* name: 'JsonWebTokenError'
+* message:
+ * 'invalid token' - the header or payload could not be parsed
+ * 'jwt malformed' - the token does not have three components (delimited by a `.`)
+ * 'jwt signature is required'
+ * 'invalid signature'
+ * 'jwt audience invalid. expected: [OPTIONS AUDIENCE]'
+ * 'jwt issuer invalid. expected: [OPTIONS ISSUER]'
+ * 'jwt id invalid. expected: [OPTIONS JWT ID]'
+ * 'jwt subject invalid. expected: [OPTIONS SUBJECT]'
+
+```js
+jwt.verify(token, 'shhhhh', function(err, decoded) {
+ if (err) {
+ /*
+ err = {
+ name: 'JsonWebTokenError',
+ message: 'jwt malformed'
+ }
+ */
+ }
+});
+```
+
+### NotBeforeError
+Thrown if current time is before the nbf claim.
+
+Error object:
+
+* name: 'NotBeforeError'
+* message: 'jwt not active'
+* date: 2018-10-04T16:10:44.000Z
+
+```js
+jwt.verify(token, 'shhhhh', function(err, decoded) {
+ if (err) {
+ /*
+ err = {
+ name: 'NotBeforeError',
+ message: 'jwt not active',
+ date: 2018-10-04T16:10:44.000Z
+ }
+ */
+ }
+});
+```
+
+
+## Algorithms supported
+
+Array of supported algorithms. The following algorithms are currently supported.
+
+| alg Parameter Value | Digital Signature or MAC Algorithm |
+|---------------------|------------------------------------------------------------------------|
+| HS256 | HMAC using SHA-256 hash algorithm |
+| HS384 | HMAC using SHA-384 hash algorithm |
+| HS512 | HMAC using SHA-512 hash algorithm |
+| RS256 | RSASSA-PKCS1-v1_5 using SHA-256 hash algorithm |
+| RS384 | RSASSA-PKCS1-v1_5 using SHA-384 hash algorithm |
+| RS512 | RSASSA-PKCS1-v1_5 using SHA-512 hash algorithm |
+| PS256 | RSASSA-PSS using SHA-256 hash algorithm (only node ^6.12.0 OR >=8.0.0) |
+| PS384 | RSASSA-PSS using SHA-384 hash algorithm (only node ^6.12.0 OR >=8.0.0) |
+| PS512 | RSASSA-PSS using SHA-512 hash algorithm (only node ^6.12.0 OR >=8.0.0) |
+| ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm |
+| ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm |
+| ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm |
+| none | No digital signature or MAC value included |
+
+## Refreshing JWTs
+
+First of all, we recommend you to think carefully if auto-refreshing a JWT will not introduce any vulnerability in your system.
+
+We are not comfortable including this as part of the library, however, you can take a look at [this example](https://gist.github.com/ziluvatar/a3feb505c4c0ec37059054537b38fc48) to show how this could be accomplished.
+Apart from that example there are [an issue](https://github.com/auth0/node-jsonwebtoken/issues/122) and [a pull request](https://github.com/auth0/node-jsonwebtoken/pull/172) to get more knowledge about this topic.
+
+# TODO
+
+* X.509 certificate chain is not checked
+
+## Issue Reporting
+
+If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues.
+
+## Author
+
+[Auth0](https://auth0.com)
+
+## License
+
+This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info.
diff --git a/node_modules/jsonwebtoken/decode.js b/node_modules/jsonwebtoken/decode.js
new file mode 100644
index 00000000..8fe1adcd
--- /dev/null
+++ b/node_modules/jsonwebtoken/decode.js
@@ -0,0 +1,30 @@
+var jws = require('jws');
+
+module.exports = function (jwt, options) {
+ options = options || {};
+ var decoded = jws.decode(jwt, options);
+ if (!decoded) { return null; }
+ var payload = decoded.payload;
+
+ //try parse the payload
+ if(typeof payload === 'string') {
+ try {
+ var obj = JSON.parse(payload);
+ if(obj !== null && typeof obj === 'object') {
+ payload = obj;
+ }
+ } catch (e) { }
+ }
+
+ //return header if `complete` option is enabled. header includes claims
+ //such as `kid` and `alg` used to select the key within a JWKS needed to
+ //verify the signature
+ if (options.complete === true) {
+ return {
+ header: decoded.header,
+ payload: payload,
+ signature: decoded.signature
+ };
+ }
+ return payload;
+};
diff --git a/node_modules/jsonwebtoken/index.js b/node_modules/jsonwebtoken/index.js
new file mode 100644
index 00000000..161eb2dd
--- /dev/null
+++ b/node_modules/jsonwebtoken/index.js
@@ -0,0 +1,8 @@
+module.exports = {
+ decode: require('./decode'),
+ verify: require('./verify'),
+ sign: require('./sign'),
+ JsonWebTokenError: require('./lib/JsonWebTokenError'),
+ NotBeforeError: require('./lib/NotBeforeError'),
+ TokenExpiredError: require('./lib/TokenExpiredError'),
+};
diff --git a/node_modules/jsonwebtoken/lib/JsonWebTokenError.js b/node_modules/jsonwebtoken/lib/JsonWebTokenError.js
new file mode 100644
index 00000000..e068222a
--- /dev/null
+++ b/node_modules/jsonwebtoken/lib/JsonWebTokenError.js
@@ -0,0 +1,14 @@
+var JsonWebTokenError = function (message, error) {
+ Error.call(this, message);
+ if(Error.captureStackTrace) {
+ Error.captureStackTrace(this, this.constructor);
+ }
+ this.name = 'JsonWebTokenError';
+ this.message = message;
+ if (error) this.inner = error;
+};
+
+JsonWebTokenError.prototype = Object.create(Error.prototype);
+JsonWebTokenError.prototype.constructor = JsonWebTokenError;
+
+module.exports = JsonWebTokenError;
diff --git a/node_modules/jsonwebtoken/lib/NotBeforeError.js b/node_modules/jsonwebtoken/lib/NotBeforeError.js
new file mode 100644
index 00000000..7b30084f
--- /dev/null
+++ b/node_modules/jsonwebtoken/lib/NotBeforeError.js
@@ -0,0 +1,13 @@
+var JsonWebTokenError = require('./JsonWebTokenError');
+
+var NotBeforeError = function (message, date) {
+ JsonWebTokenError.call(this, message);
+ this.name = 'NotBeforeError';
+ this.date = date;
+};
+
+NotBeforeError.prototype = Object.create(JsonWebTokenError.prototype);
+
+NotBeforeError.prototype.constructor = NotBeforeError;
+
+module.exports = NotBeforeError;
\ No newline at end of file
diff --git a/node_modules/jsonwebtoken/lib/TokenExpiredError.js b/node_modules/jsonwebtoken/lib/TokenExpiredError.js
new file mode 100644
index 00000000..abb704f2
--- /dev/null
+++ b/node_modules/jsonwebtoken/lib/TokenExpiredError.js
@@ -0,0 +1,13 @@
+var JsonWebTokenError = require('./JsonWebTokenError');
+
+var TokenExpiredError = function (message, expiredAt) {
+ JsonWebTokenError.call(this, message);
+ this.name = 'TokenExpiredError';
+ this.expiredAt = expiredAt;
+};
+
+TokenExpiredError.prototype = Object.create(JsonWebTokenError.prototype);
+
+TokenExpiredError.prototype.constructor = TokenExpiredError;
+
+module.exports = TokenExpiredError;
\ No newline at end of file
diff --git a/node_modules/jsonwebtoken/lib/asymmetricKeyDetailsSupported.js b/node_modules/jsonwebtoken/lib/asymmetricKeyDetailsSupported.js
new file mode 100644
index 00000000..a6ede56e
--- /dev/null
+++ b/node_modules/jsonwebtoken/lib/asymmetricKeyDetailsSupported.js
@@ -0,0 +1,3 @@
+const semver = require('semver');
+
+module.exports = semver.satisfies(process.version, '>=15.7.0');
diff --git a/node_modules/jsonwebtoken/lib/psSupported.js b/node_modules/jsonwebtoken/lib/psSupported.js
new file mode 100644
index 00000000..8c04144a
--- /dev/null
+++ b/node_modules/jsonwebtoken/lib/psSupported.js
@@ -0,0 +1,3 @@
+var semver = require('semver');
+
+module.exports = semver.satisfies(process.version, '^6.12.0 || >=8.0.0');
diff --git a/node_modules/jsonwebtoken/lib/rsaPssKeyDetailsSupported.js b/node_modules/jsonwebtoken/lib/rsaPssKeyDetailsSupported.js
new file mode 100644
index 00000000..7fcf3684
--- /dev/null
+++ b/node_modules/jsonwebtoken/lib/rsaPssKeyDetailsSupported.js
@@ -0,0 +1,3 @@
+const semver = require('semver');
+
+module.exports = semver.satisfies(process.version, '>=16.9.0');
diff --git a/node_modules/jsonwebtoken/lib/timespan.js b/node_modules/jsonwebtoken/lib/timespan.js
new file mode 100644
index 00000000..e5098690
--- /dev/null
+++ b/node_modules/jsonwebtoken/lib/timespan.js
@@ -0,0 +1,18 @@
+var ms = require('ms');
+
+module.exports = function (time, iat) {
+ var timestamp = iat || Math.floor(Date.now() / 1000);
+
+ if (typeof time === 'string') {
+ var milliseconds = ms(time);
+ if (typeof milliseconds === 'undefined') {
+ return;
+ }
+ return Math.floor(timestamp + milliseconds / 1000);
+ } else if (typeof time === 'number') {
+ return timestamp + time;
+ } else {
+ return;
+ }
+
+};
\ No newline at end of file
diff --git a/node_modules/jsonwebtoken/lib/validateAsymmetricKey.js b/node_modules/jsonwebtoken/lib/validateAsymmetricKey.js
new file mode 100644
index 00000000..c10340b0
--- /dev/null
+++ b/node_modules/jsonwebtoken/lib/validateAsymmetricKey.js
@@ -0,0 +1,66 @@
+const ASYMMETRIC_KEY_DETAILS_SUPPORTED = require('./asymmetricKeyDetailsSupported');
+const RSA_PSS_KEY_DETAILS_SUPPORTED = require('./rsaPssKeyDetailsSupported');
+
+const allowedAlgorithmsForKeys = {
+ 'ec': ['ES256', 'ES384', 'ES512'],
+ 'rsa': ['RS256', 'PS256', 'RS384', 'PS384', 'RS512', 'PS512'],
+ 'rsa-pss': ['PS256', 'PS384', 'PS512']
+};
+
+const allowedCurves = {
+ ES256: 'prime256v1',
+ ES384: 'secp384r1',
+ ES512: 'secp521r1',
+};
+
+module.exports = function(algorithm, key) {
+ if (!algorithm || !key) return;
+
+ const keyType = key.asymmetricKeyType;
+ if (!keyType) return;
+
+ const allowedAlgorithms = allowedAlgorithmsForKeys[keyType];
+
+ if (!allowedAlgorithms) {
+ throw new Error(`Unknown key type "${keyType}".`);
+ }
+
+ if (!allowedAlgorithms.includes(algorithm)) {
+ throw new Error(`"alg" parameter for "${keyType}" key type must be one of: ${allowedAlgorithms.join(', ')}.`)
+ }
+
+ /*
+ * Ignore the next block from test coverage because it gets executed
+ * conditionally depending on the Node version. Not ignoring it would
+ * prevent us from reaching the target % of coverage for versions of
+ * Node under 15.7.0.
+ */
+ /* istanbul ignore next */
+ if (ASYMMETRIC_KEY_DETAILS_SUPPORTED) {
+ switch (keyType) {
+ case 'ec':
+ const keyCurve = key.asymmetricKeyDetails.namedCurve;
+ const allowedCurve = allowedCurves[algorithm];
+
+ if (keyCurve !== allowedCurve) {
+ throw new Error(`"alg" parameter "${algorithm}" requires curve "${allowedCurve}".`);
+ }
+ break;
+
+ case 'rsa-pss':
+ if (RSA_PSS_KEY_DETAILS_SUPPORTED) {
+ const length = parseInt(algorithm.slice(-3), 10);
+ const { hashAlgorithm, mgf1HashAlgorithm, saltLength } = key.asymmetricKeyDetails;
+
+ if (hashAlgorithm !== `sha${length}` || mgf1HashAlgorithm !== hashAlgorithm) {
+ throw new Error(`Invalid key for this operation, its RSA-PSS parameters do not meet the requirements of "alg" ${algorithm}.`);
+ }
+
+ if (saltLength !== undefined && saltLength > length >> 3) {
+ throw new Error(`Invalid key for this operation, its RSA-PSS parameter saltLength does not meet the requirements of "alg" ${algorithm}.`)
+ }
+ }
+ break;
+ }
+ }
+}
diff --git a/node_modules/jsonwebtoken/package.json b/node_modules/jsonwebtoken/package.json
new file mode 100644
index 00000000..81f78da0
--- /dev/null
+++ b/node_modules/jsonwebtoken/package.json
@@ -0,0 +1,71 @@
+{
+ "name": "jsonwebtoken",
+ "version": "9.0.2",
+ "description": "JSON Web Token implementation (symmetric and asymmetric)",
+ "main": "index.js",
+ "nyc": {
+ "check-coverage": true,
+ "lines": 95,
+ "statements": 95,
+ "functions": 100,
+ "branches": 95,
+ "exclude": [
+ "./test/**"
+ ],
+ "reporter": [
+ "json",
+ "lcov",
+ "text-summary"
+ ]
+ },
+ "scripts": {
+ "lint": "eslint .",
+ "coverage": "nyc mocha --use_strict",
+ "test": "npm run lint && npm run coverage && cost-of-modules"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/auth0/node-jsonwebtoken"
+ },
+ "keywords": [
+ "jwt"
+ ],
+ "author": "auth0",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/auth0/node-jsonwebtoken/issues"
+ },
+ "dependencies": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^7.5.4"
+ },
+ "devDependencies": {
+ "atob": "^2.1.2",
+ "chai": "^4.1.2",
+ "conventional-changelog": "~1.1.0",
+ "cost-of-modules": "^1.0.1",
+ "eslint": "^4.19.1",
+ "mocha": "^5.2.0",
+ "nsp": "^2.6.2",
+ "nyc": "^11.9.0",
+ "sinon": "^6.0.0"
+ },
+ "engines": {
+ "npm": ">=6",
+ "node": ">=12"
+ },
+ "files": [
+ "lib",
+ "decode.js",
+ "sign.js",
+ "verify.js"
+ ]
+}
diff --git a/node_modules/jsonwebtoken/sign.js b/node_modules/jsonwebtoken/sign.js
new file mode 100644
index 00000000..82bf526e
--- /dev/null
+++ b/node_modules/jsonwebtoken/sign.js
@@ -0,0 +1,253 @@
+const timespan = require('./lib/timespan');
+const PS_SUPPORTED = require('./lib/psSupported');
+const validateAsymmetricKey = require('./lib/validateAsymmetricKey');
+const jws = require('jws');
+const includes = require('lodash.includes');
+const isBoolean = require('lodash.isboolean');
+const isInteger = require('lodash.isinteger');
+const isNumber = require('lodash.isnumber');
+const isPlainObject = require('lodash.isplainobject');
+const isString = require('lodash.isstring');
+const once = require('lodash.once');
+const { KeyObject, createSecretKey, createPrivateKey } = require('crypto')
+
+const SUPPORTED_ALGS = ['RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512', 'none'];
+if (PS_SUPPORTED) {
+ SUPPORTED_ALGS.splice(3, 0, 'PS256', 'PS384', 'PS512');
+}
+
+const sign_options_schema = {
+ expiresIn: { isValid: function(value) { return isInteger(value) || (isString(value) && value); }, message: '"expiresIn" should be a number of seconds or string representing a timespan' },
+ notBefore: { isValid: function(value) { return isInteger(value) || (isString(value) && value); }, message: '"notBefore" should be a number of seconds or string representing a timespan' },
+ audience: { isValid: function(value) { return isString(value) || Array.isArray(value); }, message: '"audience" must be a string or array' },
+ algorithm: { isValid: includes.bind(null, SUPPORTED_ALGS), message: '"algorithm" must be a valid string enum value' },
+ header: { isValid: isPlainObject, message: '"header" must be an object' },
+ encoding: { isValid: isString, message: '"encoding" must be a string' },
+ issuer: { isValid: isString, message: '"issuer" must be a string' },
+ subject: { isValid: isString, message: '"subject" must be a string' },
+ jwtid: { isValid: isString, message: '"jwtid" must be a string' },
+ noTimestamp: { isValid: isBoolean, message: '"noTimestamp" must be a boolean' },
+ keyid: { isValid: isString, message: '"keyid" must be a string' },
+ mutatePayload: { isValid: isBoolean, message: '"mutatePayload" must be a boolean' },
+ allowInsecureKeySizes: { isValid: isBoolean, message: '"allowInsecureKeySizes" must be a boolean'},
+ allowInvalidAsymmetricKeyTypes: { isValid: isBoolean, message: '"allowInvalidAsymmetricKeyTypes" must be a boolean'}
+};
+
+const registered_claims_schema = {
+ iat: { isValid: isNumber, message: '"iat" should be a number of seconds' },
+ exp: { isValid: isNumber, message: '"exp" should be a number of seconds' },
+ nbf: { isValid: isNumber, message: '"nbf" should be a number of seconds' }
+};
+
+function validate(schema, allowUnknown, object, parameterName) {
+ if (!isPlainObject(object)) {
+ throw new Error('Expected "' + parameterName + '" to be a plain object.');
+ }
+ Object.keys(object)
+ .forEach(function(key) {
+ const validator = schema[key];
+ if (!validator) {
+ if (!allowUnknown) {
+ throw new Error('"' + key + '" is not allowed in "' + parameterName + '"');
+ }
+ return;
+ }
+ if (!validator.isValid(object[key])) {
+ throw new Error(validator.message);
+ }
+ });
+}
+
+function validateOptions(options) {
+ return validate(sign_options_schema, false, options, 'options');
+}
+
+function validatePayload(payload) {
+ return validate(registered_claims_schema, true, payload, 'payload');
+}
+
+const options_to_payload = {
+ 'audience': 'aud',
+ 'issuer': 'iss',
+ 'subject': 'sub',
+ 'jwtid': 'jti'
+};
+
+const options_for_objects = [
+ 'expiresIn',
+ 'notBefore',
+ 'noTimestamp',
+ 'audience',
+ 'issuer',
+ 'subject',
+ 'jwtid',
+];
+
+module.exports = function (payload, secretOrPrivateKey, options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ } else {
+ options = options || {};
+ }
+
+ const isObjectPayload = typeof payload === 'object' &&
+ !Buffer.isBuffer(payload);
+
+ const header = Object.assign({
+ alg: options.algorithm || 'HS256',
+ typ: isObjectPayload ? 'JWT' : undefined,
+ kid: options.keyid
+ }, options.header);
+
+ function failure(err) {
+ if (callback) {
+ return callback(err);
+ }
+ throw err;
+ }
+
+ if (!secretOrPrivateKey && options.algorithm !== 'none') {
+ return failure(new Error('secretOrPrivateKey must have a value'));
+ }
+
+ if (secretOrPrivateKey != null && !(secretOrPrivateKey instanceof KeyObject)) {
+ try {
+ secretOrPrivateKey = createPrivateKey(secretOrPrivateKey)
+ } catch (_) {
+ try {
+ secretOrPrivateKey = createSecretKey(typeof secretOrPrivateKey === 'string' ? Buffer.from(secretOrPrivateKey) : secretOrPrivateKey)
+ } catch (_) {
+ return failure(new Error('secretOrPrivateKey is not valid key material'));
+ }
+ }
+ }
+
+ if (header.alg.startsWith('HS') && secretOrPrivateKey.type !== 'secret') {
+ return failure(new Error((`secretOrPrivateKey must be a symmetric key when using ${header.alg}`)))
+ } else if (/^(?:RS|PS|ES)/.test(header.alg)) {
+ if (secretOrPrivateKey.type !== 'private') {
+ return failure(new Error((`secretOrPrivateKey must be an asymmetric key when using ${header.alg}`)))
+ }
+ if (!options.allowInsecureKeySizes &&
+ !header.alg.startsWith('ES') &&
+ secretOrPrivateKey.asymmetricKeyDetails !== undefined && //KeyObject.asymmetricKeyDetails is supported in Node 15+
+ secretOrPrivateKey.asymmetricKeyDetails.modulusLength < 2048) {
+ return failure(new Error(`secretOrPrivateKey has a minimum key size of 2048 bits for ${header.alg}`));
+ }
+ }
+
+ if (typeof payload === 'undefined') {
+ return failure(new Error('payload is required'));
+ } else if (isObjectPayload) {
+ try {
+ validatePayload(payload);
+ }
+ catch (error) {
+ return failure(error);
+ }
+ if (!options.mutatePayload) {
+ payload = Object.assign({},payload);
+ }
+ } else {
+ const invalid_options = options_for_objects.filter(function (opt) {
+ return typeof options[opt] !== 'undefined';
+ });
+
+ if (invalid_options.length > 0) {
+ return failure(new Error('invalid ' + invalid_options.join(',') + ' option for ' + (typeof payload ) + ' payload'));
+ }
+ }
+
+ if (typeof payload.exp !== 'undefined' && typeof options.expiresIn !== 'undefined') {
+ return failure(new Error('Bad "options.expiresIn" option the payload already has an "exp" property.'));
+ }
+
+ if (typeof payload.nbf !== 'undefined' && typeof options.notBefore !== 'undefined') {
+ return failure(new Error('Bad "options.notBefore" option the payload already has an "nbf" property.'));
+ }
+
+ try {
+ validateOptions(options);
+ }
+ catch (error) {
+ return failure(error);
+ }
+
+ if (!options.allowInvalidAsymmetricKeyTypes) {
+ try {
+ validateAsymmetricKey(header.alg, secretOrPrivateKey);
+ } catch (error) {
+ return failure(error);
+ }
+ }
+
+ const timestamp = payload.iat || Math.floor(Date.now() / 1000);
+
+ if (options.noTimestamp) {
+ delete payload.iat;
+ } else if (isObjectPayload) {
+ payload.iat = timestamp;
+ }
+
+ if (typeof options.notBefore !== 'undefined') {
+ try {
+ payload.nbf = timespan(options.notBefore, timestamp);
+ }
+ catch (err) {
+ return failure(err);
+ }
+ if (typeof payload.nbf === 'undefined') {
+ return failure(new Error('"notBefore" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60'));
+ }
+ }
+
+ if (typeof options.expiresIn !== 'undefined' && typeof payload === 'object') {
+ try {
+ payload.exp = timespan(options.expiresIn, timestamp);
+ }
+ catch (err) {
+ return failure(err);
+ }
+ if (typeof payload.exp === 'undefined') {
+ return failure(new Error('"expiresIn" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60'));
+ }
+ }
+
+ Object.keys(options_to_payload).forEach(function (key) {
+ const claim = options_to_payload[key];
+ if (typeof options[key] !== 'undefined') {
+ if (typeof payload[claim] !== 'undefined') {
+ return failure(new Error('Bad "options.' + key + '" option. The payload already has an "' + claim + '" property.'));
+ }
+ payload[claim] = options[key];
+ }
+ });
+
+ const encoding = options.encoding || 'utf8';
+
+ if (typeof callback === 'function') {
+ callback = callback && once(callback);
+
+ jws.createSign({
+ header: header,
+ privateKey: secretOrPrivateKey,
+ payload: payload,
+ encoding: encoding
+ }).once('error', callback)
+ .once('done', function (signature) {
+ // TODO: Remove in favor of the modulus length check before signing once node 15+ is the minimum supported version
+ if(!options.allowInsecureKeySizes && /^(?:RS|PS)/.test(header.alg) && signature.length < 256) {
+ return callback(new Error(`secretOrPrivateKey has a minimum key size of 2048 bits for ${header.alg}`))
+ }
+ callback(null, signature);
+ });
+ } else {
+ let signature = jws.sign({header: header, payload: payload, secret: secretOrPrivateKey, encoding: encoding});
+ // TODO: Remove in favor of the modulus length check before signing once node 15+ is the minimum supported version
+ if(!options.allowInsecureKeySizes && /^(?:RS|PS)/.test(header.alg) && signature.length < 256) {
+ throw new Error(`secretOrPrivateKey has a minimum key size of 2048 bits for ${header.alg}`)
+ }
+ return signature
+ }
+};
diff --git a/node_modules/jsonwebtoken/verify.js b/node_modules/jsonwebtoken/verify.js
new file mode 100644
index 00000000..cdbfdc45
--- /dev/null
+++ b/node_modules/jsonwebtoken/verify.js
@@ -0,0 +1,263 @@
+const JsonWebTokenError = require('./lib/JsonWebTokenError');
+const NotBeforeError = require('./lib/NotBeforeError');
+const TokenExpiredError = require('./lib/TokenExpiredError');
+const decode = require('./decode');
+const timespan = require('./lib/timespan');
+const validateAsymmetricKey = require('./lib/validateAsymmetricKey');
+const PS_SUPPORTED = require('./lib/psSupported');
+const jws = require('jws');
+const {KeyObject, createSecretKey, createPublicKey} = require("crypto");
+
+const PUB_KEY_ALGS = ['RS256', 'RS384', 'RS512'];
+const EC_KEY_ALGS = ['ES256', 'ES384', 'ES512'];
+const RSA_KEY_ALGS = ['RS256', 'RS384', 'RS512'];
+const HS_ALGS = ['HS256', 'HS384', 'HS512'];
+
+if (PS_SUPPORTED) {
+ PUB_KEY_ALGS.splice(PUB_KEY_ALGS.length, 0, 'PS256', 'PS384', 'PS512');
+ RSA_KEY_ALGS.splice(RSA_KEY_ALGS.length, 0, 'PS256', 'PS384', 'PS512');
+}
+
+module.exports = function (jwtString, secretOrPublicKey, options, callback) {
+ if ((typeof options === 'function') && !callback) {
+ callback = options;
+ options = {};
+ }
+
+ if (!options) {
+ options = {};
+ }
+
+ //clone this object since we are going to mutate it.
+ options = Object.assign({}, options);
+
+ let done;
+
+ if (callback) {
+ done = callback;
+ } else {
+ done = function(err, data) {
+ if (err) throw err;
+ return data;
+ };
+ }
+
+ if (options.clockTimestamp && typeof options.clockTimestamp !== 'number') {
+ return done(new JsonWebTokenError('clockTimestamp must be a number'));
+ }
+
+ if (options.nonce !== undefined && (typeof options.nonce !== 'string' || options.nonce.trim() === '')) {
+ return done(new JsonWebTokenError('nonce must be a non-empty string'));
+ }
+
+ if (options.allowInvalidAsymmetricKeyTypes !== undefined && typeof options.allowInvalidAsymmetricKeyTypes !== 'boolean') {
+ return done(new JsonWebTokenError('allowInvalidAsymmetricKeyTypes must be a boolean'));
+ }
+
+ const clockTimestamp = options.clockTimestamp || Math.floor(Date.now() / 1000);
+
+ if (!jwtString){
+ return done(new JsonWebTokenError('jwt must be provided'));
+ }
+
+ if (typeof jwtString !== 'string') {
+ return done(new JsonWebTokenError('jwt must be a string'));
+ }
+
+ const parts = jwtString.split('.');
+
+ if (parts.length !== 3){
+ return done(new JsonWebTokenError('jwt malformed'));
+ }
+
+ let decodedToken;
+
+ try {
+ decodedToken = decode(jwtString, { complete: true });
+ } catch(err) {
+ return done(err);
+ }
+
+ if (!decodedToken) {
+ return done(new JsonWebTokenError('invalid token'));
+ }
+
+ const header = decodedToken.header;
+ let getSecret;
+
+ if(typeof secretOrPublicKey === 'function') {
+ if(!callback) {
+ return done(new JsonWebTokenError('verify must be called asynchronous if secret or public key is provided as a callback'));
+ }
+
+ getSecret = secretOrPublicKey;
+ }
+ else {
+ getSecret = function(header, secretCallback) {
+ return secretCallback(null, secretOrPublicKey);
+ };
+ }
+
+ return getSecret(header, function(err, secretOrPublicKey) {
+ if(err) {
+ return done(new JsonWebTokenError('error in secret or public key callback: ' + err.message));
+ }
+
+ const hasSignature = parts[2].trim() !== '';
+
+ if (!hasSignature && secretOrPublicKey){
+ return done(new JsonWebTokenError('jwt signature is required'));
+ }
+
+ if (hasSignature && !secretOrPublicKey) {
+ return done(new JsonWebTokenError('secret or public key must be provided'));
+ }
+
+ if (!hasSignature && !options.algorithms) {
+ return done(new JsonWebTokenError('please specify "none" in "algorithms" to verify unsigned tokens'));
+ }
+
+ if (secretOrPublicKey != null && !(secretOrPublicKey instanceof KeyObject)) {
+ try {
+ secretOrPublicKey = createPublicKey(secretOrPublicKey);
+ } catch (_) {
+ try {
+ secretOrPublicKey = createSecretKey(typeof secretOrPublicKey === 'string' ? Buffer.from(secretOrPublicKey) : secretOrPublicKey);
+ } catch (_) {
+ return done(new JsonWebTokenError('secretOrPublicKey is not valid key material'))
+ }
+ }
+ }
+
+ if (!options.algorithms) {
+ if (secretOrPublicKey.type === 'secret') {
+ options.algorithms = HS_ALGS;
+ } else if (['rsa', 'rsa-pss'].includes(secretOrPublicKey.asymmetricKeyType)) {
+ options.algorithms = RSA_KEY_ALGS
+ } else if (secretOrPublicKey.asymmetricKeyType === 'ec') {
+ options.algorithms = EC_KEY_ALGS
+ } else {
+ options.algorithms = PUB_KEY_ALGS
+ }
+ }
+
+ if (options.algorithms.indexOf(decodedToken.header.alg) === -1) {
+ return done(new JsonWebTokenError('invalid algorithm'));
+ }
+
+ if (header.alg.startsWith('HS') && secretOrPublicKey.type !== 'secret') {
+ return done(new JsonWebTokenError((`secretOrPublicKey must be a symmetric key when using ${header.alg}`)))
+ } else if (/^(?:RS|PS|ES)/.test(header.alg) && secretOrPublicKey.type !== 'public') {
+ return done(new JsonWebTokenError((`secretOrPublicKey must be an asymmetric key when using ${header.alg}`)))
+ }
+
+ if (!options.allowInvalidAsymmetricKeyTypes) {
+ try {
+ validateAsymmetricKey(header.alg, secretOrPublicKey);
+ } catch (e) {
+ return done(e);
+ }
+ }
+
+ let valid;
+
+ try {
+ valid = jws.verify(jwtString, decodedToken.header.alg, secretOrPublicKey);
+ } catch (e) {
+ return done(e);
+ }
+
+ if (!valid) {
+ return done(new JsonWebTokenError('invalid signature'));
+ }
+
+ const payload = decodedToken.payload;
+
+ if (typeof payload.nbf !== 'undefined' && !options.ignoreNotBefore) {
+ if (typeof payload.nbf !== 'number') {
+ return done(new JsonWebTokenError('invalid nbf value'));
+ }
+ if (payload.nbf > clockTimestamp + (options.clockTolerance || 0)) {
+ return done(new NotBeforeError('jwt not active', new Date(payload.nbf * 1000)));
+ }
+ }
+
+ if (typeof payload.exp !== 'undefined' && !options.ignoreExpiration) {
+ if (typeof payload.exp !== 'number') {
+ return done(new JsonWebTokenError('invalid exp value'));
+ }
+ if (clockTimestamp >= payload.exp + (options.clockTolerance || 0)) {
+ return done(new TokenExpiredError('jwt expired', new Date(payload.exp * 1000)));
+ }
+ }
+
+ if (options.audience) {
+ const audiences = Array.isArray(options.audience) ? options.audience : [options.audience];
+ const target = Array.isArray(payload.aud) ? payload.aud : [payload.aud];
+
+ const match = target.some(function (targetAudience) {
+ return audiences.some(function (audience) {
+ return audience instanceof RegExp ? audience.test(targetAudience) : audience === targetAudience;
+ });
+ });
+
+ if (!match) {
+ return done(new JsonWebTokenError('jwt audience invalid. expected: ' + audiences.join(' or ')));
+ }
+ }
+
+ if (options.issuer) {
+ const invalid_issuer =
+ (typeof options.issuer === 'string' && payload.iss !== options.issuer) ||
+ (Array.isArray(options.issuer) && options.issuer.indexOf(payload.iss) === -1);
+
+ if (invalid_issuer) {
+ return done(new JsonWebTokenError('jwt issuer invalid. expected: ' + options.issuer));
+ }
+ }
+
+ if (options.subject) {
+ if (payload.sub !== options.subject) {
+ return done(new JsonWebTokenError('jwt subject invalid. expected: ' + options.subject));
+ }
+ }
+
+ if (options.jwtid) {
+ if (payload.jti !== options.jwtid) {
+ return done(new JsonWebTokenError('jwt jwtid invalid. expected: ' + options.jwtid));
+ }
+ }
+
+ if (options.nonce) {
+ if (payload.nonce !== options.nonce) {
+ return done(new JsonWebTokenError('jwt nonce invalid. expected: ' + options.nonce));
+ }
+ }
+
+ if (options.maxAge) {
+ if (typeof payload.iat !== 'number') {
+ return done(new JsonWebTokenError('iat required when maxAge is specified'));
+ }
+
+ const maxAgeTimestamp = timespan(options.maxAge, payload.iat);
+ if (typeof maxAgeTimestamp === 'undefined') {
+ return done(new JsonWebTokenError('"maxAge" should be a number of seconds or string representing a timespan eg: "1d", "20h", 60'));
+ }
+ if (clockTimestamp >= maxAgeTimestamp + (options.clockTolerance || 0)) {
+ return done(new TokenExpiredError('maxAge exceeded', new Date(maxAgeTimestamp * 1000)));
+ }
+ }
+
+ if (options.complete === true) {
+ const signature = decodedToken.signature;
+
+ return done(null, {
+ header: header,
+ payload: payload,
+ signature: signature
+ });
+ }
+
+ return done(null, payload);
+ });
+};
diff --git a/node_modules/jwa/LICENSE b/node_modules/jwa/LICENSE
new file mode 100644
index 00000000..caeb8495
--- /dev/null
+++ b/node_modules/jwa/LICENSE
@@ -0,0 +1,17 @@
+Copyright (c) 2013 Brian J. Brennan
+
+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/jwa/README.md b/node_modules/jwa/README.md
new file mode 100644
index 00000000..fb433e23
--- /dev/null
+++ b/node_modules/jwa/README.md
@@ -0,0 +1,150 @@
+# node-jwa [](https://travis-ci.org/brianloveswords/node-jwa)
+
+A
+[JSON Web Algorithms](http://tools.ietf.org/id/draft-ietf-jose-json-web-algorithms-08.html)
+implementation focusing (exclusively, at this point) on the algorithms necessary for
+[JSON Web Signatures](http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html).
+
+This library supports all of the required, recommended and optional cryptographic algorithms for JWS:
+
+alg Parameter Value | Digital Signature or MAC Algorithm
+----------------|----------------------------
+HS256 | HMAC using SHA-256 hash algorithm
+HS384 | HMAC using SHA-384 hash algorithm
+HS512 | HMAC using SHA-512 hash algorithm
+RS256 | RSASSA using SHA-256 hash algorithm
+RS384 | RSASSA using SHA-384 hash algorithm
+RS512 | RSASSA using SHA-512 hash algorithm
+PS256 | RSASSA-PSS using SHA-256 hash algorithm
+PS384 | RSASSA-PSS using SHA-384 hash algorithm
+PS512 | RSASSA-PSS using SHA-512 hash algorithm
+ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm
+ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm
+ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm
+none | No digital signature or MAC value included
+
+Please note that PS* only works on Node 6.12+ (excluding 7.x).
+
+# Requirements
+
+In order to run the tests, a recent version of OpenSSL is
+required. **The version that comes with OS X (OpenSSL 0.9.8r 8 Feb
+2011) is not recent enough**, as it does not fully support ECDSA
+keys. You'll need to use a version > 1.0.0; I tested with OpenSSL 1.0.1c 10 May 2012.
+
+# Testing
+
+To run the tests, do
+
+```bash
+$ npm test
+```
+
+This will generate a bunch of keypairs to use in testing. If you want to
+generate new keypairs, do `make clean` before running `npm test` again.
+
+## Methodology
+
+I spawn `openssl dgst -sign` to test OpenSSL sign â JS verify and
+`openssl dgst -verify` to test JS sign â OpenSSL verify for each of the
+RSA and ECDSA algorithms.
+
+# Usage
+
+## jwa(algorithm)
+
+Creates a new `jwa` object with `sign` and `verify` methods for the
+algorithm. Valid values for algorithm can be found in the table above
+(`'HS256'`, `'HS384'`, etc) and are case-insensitive. Passing an invalid
+algorithm value will throw a `TypeError`.
+
+
+## jwa#sign(input, secretOrPrivateKey)
+
+Sign some input with either a secret for HMAC algorithms, or a private
+key for RSA and ECDSA algorithms.
+
+If input is not already a string or buffer, `JSON.stringify` will be
+called on it to attempt to coerce it.
+
+For the HMAC algorithm, `secretOrPrivateKey` should be a string or a
+buffer. For ECDSA and RSA, the value should be a string representing a
+PEM encoded **private** key.
+
+Output [base64url](http://en.wikipedia.org/wiki/Base64#URL_applications)
+formatted. This is for convenience as JWS expects the signature in this
+format. If your application needs the output in a different format,
+[please open an issue](https://github.com/brianloveswords/node-jwa/issues). In
+the meantime, you can use
+[brianloveswords/base64url](https://github.com/brianloveswords/base64url)
+to decode the signature.
+
+As of nodejs *v0.11.8*, SPKAC support was introduce. If your nodeJs
+version satisfies, then you can pass an object `{ key: '..', passphrase: '...' }`
+
+
+## jwa#verify(input, signature, secretOrPublicKey)
+
+Verify a signature. Returns `true` or `false`.
+
+`signature` should be a base64url encoded string.
+
+For the HMAC algorithm, `secretOrPublicKey` should be a string or a
+buffer. For ECDSA and RSA, the value should be a string represented a
+PEM encoded **public** key.
+
+
+# Example
+
+HMAC
+```js
+const jwa = require('jwa');
+
+const hmac = jwa('HS256');
+const input = 'super important stuff';
+const secret = 'shhhhhh';
+
+const signature = hmac.sign(input, secret);
+hmac.verify(input, signature, secret) // === true
+hmac.verify(input, signature, 'trickery!') // === false
+```
+
+With keys
+```js
+const fs = require('fs');
+const jwa = require('jwa');
+const privateKey = fs.readFileSync(__dirname + '/ecdsa-p521-private.pem');
+const publicKey = fs.readFileSync(__dirname + '/ecdsa-p521-public.pem');
+
+const ecdsa = jwa('ES512');
+const input = 'very important stuff';
+
+const signature = ecdsa.sign(input, privateKey);
+ecdsa.verify(input, signature, publicKey) // === true
+```
+## License
+
+MIT
+
+```
+Copyright (c) 2013 Brian J. Brennan
+
+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/jwa/index.js b/node_modules/jwa/index.js
new file mode 100644
index 00000000..5c1b6cfc
--- /dev/null
+++ b/node_modules/jwa/index.js
@@ -0,0 +1,266 @@
+var Buffer = require('safe-buffer').Buffer;
+var crypto = require('crypto');
+var formatEcdsa = require('ecdsa-sig-formatter');
+var util = require('util');
+
+var MSG_INVALID_ALGORITHM = '"%s" is not a valid algorithm.\n Supported algorithms are:\n "HS256", "HS384", "HS512", "RS256", "RS384", "RS512", "PS256", "PS384", "PS512", "ES256", "ES384", "ES512" and "none".'
+var MSG_INVALID_SECRET = 'secret must be a string or buffer';
+var MSG_INVALID_VERIFIER_KEY = 'key must be a string or a buffer';
+var MSG_INVALID_SIGNER_KEY = 'key must be a string, a buffer or an object';
+
+var supportsKeyObjects = typeof crypto.createPublicKey === 'function';
+if (supportsKeyObjects) {
+ MSG_INVALID_VERIFIER_KEY += ' or a KeyObject';
+ MSG_INVALID_SECRET += 'or a KeyObject';
+}
+
+function checkIsPublicKey(key) {
+ if (Buffer.isBuffer(key)) {
+ return;
+ }
+
+ if (typeof key === 'string') {
+ return;
+ }
+
+ if (!supportsKeyObjects) {
+ throw typeError(MSG_INVALID_VERIFIER_KEY);
+ }
+
+ if (typeof key !== 'object') {
+ throw typeError(MSG_INVALID_VERIFIER_KEY);
+ }
+
+ if (typeof key.type !== 'string') {
+ throw typeError(MSG_INVALID_VERIFIER_KEY);
+ }
+
+ if (typeof key.asymmetricKeyType !== 'string') {
+ throw typeError(MSG_INVALID_VERIFIER_KEY);
+ }
+
+ if (typeof key.export !== 'function') {
+ throw typeError(MSG_INVALID_VERIFIER_KEY);
+ }
+};
+
+function checkIsPrivateKey(key) {
+ if (Buffer.isBuffer(key)) {
+ return;
+ }
+
+ if (typeof key === 'string') {
+ return;
+ }
+
+ if (typeof key === 'object') {
+ return;
+ }
+
+ throw typeError(MSG_INVALID_SIGNER_KEY);
+};
+
+function checkIsSecretKey(key) {
+ if (Buffer.isBuffer(key)) {
+ return;
+ }
+
+ if (typeof key === 'string') {
+ return key;
+ }
+
+ if (!supportsKeyObjects) {
+ throw typeError(MSG_INVALID_SECRET);
+ }
+
+ if (typeof key !== 'object') {
+ throw typeError(MSG_INVALID_SECRET);
+ }
+
+ if (key.type !== 'secret') {
+ throw typeError(MSG_INVALID_SECRET);
+ }
+
+ if (typeof key.export !== 'function') {
+ throw typeError(MSG_INVALID_SECRET);
+ }
+}
+
+function fromBase64(base64) {
+ return base64
+ .replace(/=/g, '')
+ .replace(/\+/g, '-')
+ .replace(/\//g, '_');
+}
+
+function toBase64(base64url) {
+ base64url = base64url.toString();
+
+ var padding = 4 - base64url.length % 4;
+ if (padding !== 4) {
+ for (var i = 0; i < padding; ++i) {
+ base64url += '=';
+ }
+ }
+
+ return base64url
+ .replace(/\-/g, '+')
+ .replace(/_/g, '/');
+}
+
+function typeError(template) {
+ var args = [].slice.call(arguments, 1);
+ var errMsg = util.format.bind(util, template).apply(null, args);
+ return new TypeError(errMsg);
+}
+
+function bufferOrString(obj) {
+ return Buffer.isBuffer(obj) || typeof obj === 'string';
+}
+
+function normalizeInput(thing) {
+ if (!bufferOrString(thing))
+ thing = JSON.stringify(thing);
+ return thing;
+}
+
+function createHmacSigner(bits) {
+ return function sign(thing, secret) {
+ checkIsSecretKey(secret);
+ thing = normalizeInput(thing);
+ var hmac = crypto.createHmac('sha' + bits, secret);
+ var sig = (hmac.update(thing), hmac.digest('base64'))
+ return fromBase64(sig);
+ }
+}
+
+var bufferEqual;
+var timingSafeEqual = 'timingSafeEqual' in crypto ? function timingSafeEqual(a, b) {
+ if (a.byteLength !== b.byteLength) {
+ return false;
+ }
+
+ return crypto.timingSafeEqual(a, b)
+} : function timingSafeEqual(a, b) {
+ if (!bufferEqual) {
+ bufferEqual = require('buffer-equal-constant-time');
+ }
+
+ return bufferEqual(a, b)
+}
+
+function createHmacVerifier(bits) {
+ return function verify(thing, signature, secret) {
+ var computedSig = createHmacSigner(bits)(thing, secret);
+ return timingSafeEqual(Buffer.from(signature), Buffer.from(computedSig));
+ }
+}
+
+function createKeySigner(bits) {
+ return function sign(thing, privateKey) {
+ checkIsPrivateKey(privateKey);
+ thing = normalizeInput(thing);
+ // Even though we are specifying "RSA" here, this works with ECDSA
+ // keys as well.
+ var signer = crypto.createSign('RSA-SHA' + bits);
+ var sig = (signer.update(thing), signer.sign(privateKey, 'base64'));
+ return fromBase64(sig);
+ }
+}
+
+function createKeyVerifier(bits) {
+ return function verify(thing, signature, publicKey) {
+ checkIsPublicKey(publicKey);
+ thing = normalizeInput(thing);
+ signature = toBase64(signature);
+ var verifier = crypto.createVerify('RSA-SHA' + bits);
+ verifier.update(thing);
+ return verifier.verify(publicKey, signature, 'base64');
+ }
+}
+
+function createPSSKeySigner(bits) {
+ return function sign(thing, privateKey) {
+ checkIsPrivateKey(privateKey);
+ thing = normalizeInput(thing);
+ var signer = crypto.createSign('RSA-SHA' + bits);
+ var sig = (signer.update(thing), signer.sign({
+ key: privateKey,
+ padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
+ saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST
+ }, 'base64'));
+ return fromBase64(sig);
+ }
+}
+
+function createPSSKeyVerifier(bits) {
+ return function verify(thing, signature, publicKey) {
+ checkIsPublicKey(publicKey);
+ thing = normalizeInput(thing);
+ signature = toBase64(signature);
+ var verifier = crypto.createVerify('RSA-SHA' + bits);
+ verifier.update(thing);
+ return verifier.verify({
+ key: publicKey,
+ padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
+ saltLength: crypto.constants.RSA_PSS_SALTLEN_DIGEST
+ }, signature, 'base64');
+ }
+}
+
+function createECDSASigner(bits) {
+ var inner = createKeySigner(bits);
+ return function sign() {
+ var signature = inner.apply(null, arguments);
+ signature = formatEcdsa.derToJose(signature, 'ES' + bits);
+ return signature;
+ };
+}
+
+function createECDSAVerifer(bits) {
+ var inner = createKeyVerifier(bits);
+ return function verify(thing, signature, publicKey) {
+ signature = formatEcdsa.joseToDer(signature, 'ES' + bits).toString('base64');
+ var result = inner(thing, signature, publicKey);
+ return result;
+ };
+}
+
+function createNoneSigner() {
+ return function sign() {
+ return '';
+ }
+}
+
+function createNoneVerifier() {
+ return function verify(thing, signature) {
+ return signature === '';
+ }
+}
+
+module.exports = function jwa(algorithm) {
+ var signerFactories = {
+ hs: createHmacSigner,
+ rs: createKeySigner,
+ ps: createPSSKeySigner,
+ es: createECDSASigner,
+ none: createNoneSigner,
+ }
+ var verifierFactories = {
+ hs: createHmacVerifier,
+ rs: createKeyVerifier,
+ ps: createPSSKeyVerifier,
+ es: createECDSAVerifer,
+ none: createNoneVerifier,
+ }
+ var match = algorithm.match(/^(RS|PS|ES|HS)(256|384|512)$|^(none)$/i);
+ if (!match)
+ throw typeError(MSG_INVALID_ALGORITHM, algorithm);
+ var algo = (match[1] || match[3]).toLowerCase();
+ var bits = match[2];
+
+ return {
+ sign: signerFactories[algo](bits),
+ verify: verifierFactories[algo](bits),
+ }
+};
diff --git a/node_modules/jwa/package.json b/node_modules/jwa/package.json
new file mode 100644
index 00000000..be9b11fb
--- /dev/null
+++ b/node_modules/jwa/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "jwa",
+ "version": "1.4.2",
+ "description": "JWA implementation (supports all JWS algorithms)",
+ "main": "index.js",
+ "directories": {
+ "test": "test"
+ },
+ "dependencies": {
+ "buffer-equal-constant-time": "^1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ },
+ "devDependencies": {
+ "base64url": "^2.0.0",
+ "jwk-to-pem": "^2.0.1",
+ "semver": "4.3.6",
+ "tap": "6.2.0"
+ },
+ "scripts": {
+ "test": "make test"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/brianloveswords/node-jwa.git"
+ },
+ "keywords": [
+ "jwa",
+ "jws",
+ "jwt",
+ "rsa",
+ "ecdsa",
+ "hmac"
+ ],
+ "author": "Brian J. Brennan ",
+ "license": "MIT"
+}
diff --git a/node_modules/jws/CHANGELOG.md b/node_modules/jws/CHANGELOG.md
new file mode 100644
index 00000000..af8fc287
--- /dev/null
+++ b/node_modules/jws/CHANGELOG.md
@@ -0,0 +1,34 @@
+# Change Log
+All notable changes to this project will be documented in this file.
+
+## [3.0.0]
+### Changed
+- **BREAKING**: `jwt.verify` now requires an `algorithm` parameter, and
+ `jws.createVerify` requires an `algorithm` option. The `"alg"` field
+ signature headers is ignored. This mitigates a critical security flaw
+ in the library which would allow an attacker to generate signatures with
+ arbitrary contents that would be accepted by `jwt.verify`. See
+ https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
+ for details.
+
+## [2.0.0] - 2015-01-30
+### Changed
+- **BREAKING**: Default payload encoding changed from `binary` to
+ `utf8`. `utf8` is a is a more sensible default than `binary` because
+ many payloads, as far as I can tell, will contain user-facing
+ strings that could be in any language. ([6b6de48])
+
+- Code reorganization, thanks [@fearphage]! ([7880050])
+
+### Added
+- Option in all relevant methods for `encoding`. For those few users
+ that might be depending on a `binary` encoding of the messages, this
+ is for them. ([6b6de48])
+
+[unreleased]: https://github.com/brianloveswords/node-jws/compare/v2.0.0...HEAD
+[2.0.0]: https://github.com/brianloveswords/node-jws/compare/v1.0.1...v2.0.0
+
+[7880050]: https://github.com/brianloveswords/node-jws/commit/7880050
+[6b6de48]: https://github.com/brianloveswords/node-jws/commit/6b6de48
+
+[@fearphage]: https://github.com/fearphage
diff --git a/node_modules/jws/LICENSE b/node_modules/jws/LICENSE
new file mode 100644
index 00000000..caeb8495
--- /dev/null
+++ b/node_modules/jws/LICENSE
@@ -0,0 +1,17 @@
+Copyright (c) 2013 Brian J. Brennan
+
+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/jws/index.js b/node_modules/jws/index.js
new file mode 100644
index 00000000..8c8da930
--- /dev/null
+++ b/node_modules/jws/index.js
@@ -0,0 +1,22 @@
+/*global exports*/
+var SignStream = require('./lib/sign-stream');
+var VerifyStream = require('./lib/verify-stream');
+
+var ALGORITHMS = [
+ 'HS256', 'HS384', 'HS512',
+ 'RS256', 'RS384', 'RS512',
+ 'PS256', 'PS384', 'PS512',
+ 'ES256', 'ES384', 'ES512'
+];
+
+exports.ALGORITHMS = ALGORITHMS;
+exports.sign = SignStream.sign;
+exports.verify = VerifyStream.verify;
+exports.decode = VerifyStream.decode;
+exports.isValid = VerifyStream.isValid;
+exports.createSign = function createSign(opts) {
+ return new SignStream(opts);
+};
+exports.createVerify = function createVerify(opts) {
+ return new VerifyStream(opts);
+};
diff --git a/node_modules/jws/lib/data-stream.js b/node_modules/jws/lib/data-stream.js
new file mode 100644
index 00000000..3535d31d
--- /dev/null
+++ b/node_modules/jws/lib/data-stream.js
@@ -0,0 +1,55 @@
+/*global module, process*/
+var Buffer = require('safe-buffer').Buffer;
+var Stream = require('stream');
+var util = require('util');
+
+function DataStream(data) {
+ this.buffer = null;
+ this.writable = true;
+ this.readable = true;
+
+ // No input
+ if (!data) {
+ this.buffer = Buffer.alloc(0);
+ return this;
+ }
+
+ // Stream
+ if (typeof data.pipe === 'function') {
+ this.buffer = Buffer.alloc(0);
+ data.pipe(this);
+ return this;
+ }
+
+ // Buffer or String
+ // or Object (assumedly a passworded key)
+ if (data.length || typeof data === 'object') {
+ this.buffer = data;
+ this.writable = false;
+ process.nextTick(function () {
+ this.emit('end', data);
+ this.readable = false;
+ this.emit('close');
+ }.bind(this));
+ return this;
+ }
+
+ throw new TypeError('Unexpected data type ('+ typeof data + ')');
+}
+util.inherits(DataStream, Stream);
+
+DataStream.prototype.write = function write(data) {
+ this.buffer = Buffer.concat([this.buffer, Buffer.from(data)]);
+ this.emit('data', data);
+};
+
+DataStream.prototype.end = function end(data) {
+ if (data)
+ this.write(data);
+ this.emit('end', data);
+ this.emit('close');
+ this.writable = false;
+ this.readable = false;
+};
+
+module.exports = DataStream;
diff --git a/node_modules/jws/lib/sign-stream.js b/node_modules/jws/lib/sign-stream.js
new file mode 100644
index 00000000..6a7ee42f
--- /dev/null
+++ b/node_modules/jws/lib/sign-stream.js
@@ -0,0 +1,78 @@
+/*global module*/
+var Buffer = require('safe-buffer').Buffer;
+var DataStream = require('./data-stream');
+var jwa = require('jwa');
+var Stream = require('stream');
+var toString = require('./tostring');
+var util = require('util');
+
+function base64url(string, encoding) {
+ return Buffer
+ .from(string, encoding)
+ .toString('base64')
+ .replace(/=/g, '')
+ .replace(/\+/g, '-')
+ .replace(/\//g, '_');
+}
+
+function jwsSecuredInput(header, payload, encoding) {
+ encoding = encoding || 'utf8';
+ var encodedHeader = base64url(toString(header), 'binary');
+ var encodedPayload = base64url(toString(payload), encoding);
+ return util.format('%s.%s', encodedHeader, encodedPayload);
+}
+
+function jwsSign(opts) {
+ var header = opts.header;
+ var payload = opts.payload;
+ var secretOrKey = opts.secret || opts.privateKey;
+ var encoding = opts.encoding;
+ var algo = jwa(header.alg);
+ var securedInput = jwsSecuredInput(header, payload, encoding);
+ var signature = algo.sign(securedInput, secretOrKey);
+ return util.format('%s.%s', securedInput, signature);
+}
+
+function SignStream(opts) {
+ var secret = opts.secret||opts.privateKey||opts.key;
+ var secretStream = new DataStream(secret);
+ this.readable = true;
+ this.header = opts.header;
+ this.encoding = opts.encoding;
+ this.secret = this.privateKey = this.key = secretStream;
+ this.payload = new DataStream(opts.payload);
+ this.secret.once('close', function () {
+ if (!this.payload.writable && this.readable)
+ this.sign();
+ }.bind(this));
+
+ this.payload.once('close', function () {
+ if (!this.secret.writable && this.readable)
+ this.sign();
+ }.bind(this));
+}
+util.inherits(SignStream, Stream);
+
+SignStream.prototype.sign = function sign() {
+ try {
+ var signature = jwsSign({
+ header: this.header,
+ payload: this.payload.buffer,
+ secret: this.secret.buffer,
+ encoding: this.encoding
+ });
+ this.emit('done', signature);
+ this.emit('data', signature);
+ this.emit('end');
+ this.readable = false;
+ return signature;
+ } catch (e) {
+ this.readable = false;
+ this.emit('error', e);
+ this.emit('close');
+ }
+};
+
+SignStream.sign = jwsSign;
+
+module.exports = SignStream;
diff --git a/node_modules/jws/lib/tostring.js b/node_modules/jws/lib/tostring.js
new file mode 100644
index 00000000..f5a49a36
--- /dev/null
+++ b/node_modules/jws/lib/tostring.js
@@ -0,0 +1,10 @@
+/*global module*/
+var Buffer = require('buffer').Buffer;
+
+module.exports = function toString(obj) {
+ if (typeof obj === 'string')
+ return obj;
+ if (typeof obj === 'number' || Buffer.isBuffer(obj))
+ return obj.toString();
+ return JSON.stringify(obj);
+};
diff --git a/node_modules/jws/lib/verify-stream.js b/node_modules/jws/lib/verify-stream.js
new file mode 100644
index 00000000..39f7c73e
--- /dev/null
+++ b/node_modules/jws/lib/verify-stream.js
@@ -0,0 +1,120 @@
+/*global module*/
+var Buffer = require('safe-buffer').Buffer;
+var DataStream = require('./data-stream');
+var jwa = require('jwa');
+var Stream = require('stream');
+var toString = require('./tostring');
+var util = require('util');
+var JWS_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/;
+
+function isObject(thing) {
+ return Object.prototype.toString.call(thing) === '[object Object]';
+}
+
+function safeJsonParse(thing) {
+ if (isObject(thing))
+ return thing;
+ try { return JSON.parse(thing); }
+ catch (e) { return undefined; }
+}
+
+function headerFromJWS(jwsSig) {
+ var encodedHeader = jwsSig.split('.', 1)[0];
+ return safeJsonParse(Buffer.from(encodedHeader, 'base64').toString('binary'));
+}
+
+function securedInputFromJWS(jwsSig) {
+ return jwsSig.split('.', 2).join('.');
+}
+
+function signatureFromJWS(jwsSig) {
+ return jwsSig.split('.')[2];
+}
+
+function payloadFromJWS(jwsSig, encoding) {
+ encoding = encoding || 'utf8';
+ var payload = jwsSig.split('.')[1];
+ return Buffer.from(payload, 'base64').toString(encoding);
+}
+
+function isValidJws(string) {
+ return JWS_REGEX.test(string) && !!headerFromJWS(string);
+}
+
+function jwsVerify(jwsSig, algorithm, secretOrKey) {
+ if (!algorithm) {
+ var err = new Error("Missing algorithm parameter for jws.verify");
+ err.code = "MISSING_ALGORITHM";
+ throw err;
+ }
+ jwsSig = toString(jwsSig);
+ var signature = signatureFromJWS(jwsSig);
+ var securedInput = securedInputFromJWS(jwsSig);
+ var algo = jwa(algorithm);
+ return algo.verify(securedInput, signature, secretOrKey);
+}
+
+function jwsDecode(jwsSig, opts) {
+ opts = opts || {};
+ jwsSig = toString(jwsSig);
+
+ if (!isValidJws(jwsSig))
+ return null;
+
+ var header = headerFromJWS(jwsSig);
+
+ if (!header)
+ return null;
+
+ var payload = payloadFromJWS(jwsSig);
+ if (header.typ === 'JWT' || opts.json)
+ payload = JSON.parse(payload, opts.encoding);
+
+ return {
+ header: header,
+ payload: payload,
+ signature: signatureFromJWS(jwsSig)
+ };
+}
+
+function VerifyStream(opts) {
+ opts = opts || {};
+ var secretOrKey = opts.secret||opts.publicKey||opts.key;
+ var secretStream = new DataStream(secretOrKey);
+ this.readable = true;
+ this.algorithm = opts.algorithm;
+ this.encoding = opts.encoding;
+ this.secret = this.publicKey = this.key = secretStream;
+ this.signature = new DataStream(opts.signature);
+ this.secret.once('close', function () {
+ if (!this.signature.writable && this.readable)
+ this.verify();
+ }.bind(this));
+
+ this.signature.once('close', function () {
+ if (!this.secret.writable && this.readable)
+ this.verify();
+ }.bind(this));
+}
+util.inherits(VerifyStream, Stream);
+VerifyStream.prototype.verify = function verify() {
+ try {
+ var valid = jwsVerify(this.signature.buffer, this.algorithm, this.key.buffer);
+ var obj = jwsDecode(this.signature.buffer, this.encoding);
+ this.emit('done', valid, obj);
+ this.emit('data', valid);
+ this.emit('end');
+ this.readable = false;
+ return valid;
+ } catch (e) {
+ this.readable = false;
+ this.emit('error', e);
+ this.emit('close');
+ }
+};
+
+VerifyStream.decode = jwsDecode;
+VerifyStream.isValid = isValidJws;
+VerifyStream.verify = jwsVerify;
+
+module.exports = VerifyStream;
diff --git a/node_modules/jws/package.json b/node_modules/jws/package.json
new file mode 100644
index 00000000..3fb28375
--- /dev/null
+++ b/node_modules/jws/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "jws",
+ "version": "3.2.2",
+ "description": "Implementation of JSON Web Signatures",
+ "main": "index.js",
+ "directories": {
+ "test": "test"
+ },
+ "scripts": {
+ "test": "make test"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/brianloveswords/node-jws.git"
+ },
+ "keywords": [
+ "jws",
+ "json",
+ "web",
+ "signatures"
+ ],
+ "author": "Brian J Brennan",
+ "license": "MIT",
+ "readmeFilename": "readme.md",
+ "gitHead": "c0f6b27bcea5a2ad2e304d91c2e842e4076a6b03",
+ "dependencies": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ },
+ "devDependencies": {
+ "semver": "^5.1.0",
+ "tape": "~2.14.0"
+ }
+}
diff --git a/node_modules/jws/readme.md b/node_modules/jws/readme.md
new file mode 100644
index 00000000..1910c9a8
--- /dev/null
+++ b/node_modules/jws/readme.md
@@ -0,0 +1,255 @@
+# node-jws [](http://travis-ci.org/brianloveswords/node-jws)
+
+An implementation of [JSON Web Signatures](http://self-issued.info/docs/draft-ietf-jose-json-web-signature.html).
+
+This was developed against `draft-ietf-jose-json-web-signature-08` and
+implements the entire spec **except** X.509 Certificate Chain
+signing/verifying (patches welcome).
+
+There are both synchronous (`jws.sign`, `jws.verify`) and streaming
+(`jws.createSign`, `jws.createVerify`) APIs.
+
+# Install
+
+```bash
+$ npm install jws
+```
+
+# Usage
+
+## jws.ALGORITHMS
+
+Array of supported algorithms. The following algorithms are currently supported.
+
+alg Parameter Value | Digital Signature or MAC Algorithm
+----------------|----------------------------
+HS256 | HMAC using SHA-256 hash algorithm
+HS384 | HMAC using SHA-384 hash algorithm
+HS512 | HMAC using SHA-512 hash algorithm
+RS256 | RSASSA using SHA-256 hash algorithm
+RS384 | RSASSA using SHA-384 hash algorithm
+RS512 | RSASSA using SHA-512 hash algorithm
+PS256 | RSASSA-PSS using SHA-256 hash algorithm
+PS384 | RSASSA-PSS using SHA-384 hash algorithm
+PS512 | RSASSA-PSS using SHA-512 hash algorithm
+ES256 | ECDSA using P-256 curve and SHA-256 hash algorithm
+ES384 | ECDSA using P-384 curve and SHA-384 hash algorithm
+ES512 | ECDSA using P-521 curve and SHA-512 hash algorithm
+none | No digital signature or MAC value included
+
+## jws.sign(options)
+
+(Synchronous) Return a JSON Web Signature for a header and a payload.
+
+Options:
+
+* `header`
+* `payload`
+* `secret` or `privateKey`
+* `encoding` (Optional, defaults to 'utf8')
+
+`header` must be an object with an `alg` property. `header.alg` must be
+one a value found in `jws.ALGORITHMS`. See above for a table of
+supported algorithms.
+
+If `payload` is not a buffer or a string, it will be coerced into a string
+using `JSON.stringify`.
+
+Example
+
+```js
+const signature = jws.sign({
+ header: { alg: 'HS256' },
+ payload: 'h. jon benjamin',
+ secret: 'has a van',
+});
+```
+
+## jws.verify(signature, algorithm, secretOrKey)
+
+(Synchronous) Returns `true` or `false` for whether a signature matches a
+secret or key.
+
+`signature` is a JWS Signature. `header.alg` must be a value found in `jws.ALGORITHMS`.
+See above for a table of supported algorithms. `secretOrKey` is a string or
+buffer containing either the secret for HMAC algorithms, or the PEM
+encoded public key for RSA and ECDSA.
+
+Note that the `"alg"` value from the signature header is ignored.
+
+
+## jws.decode(signature)
+
+(Synchronous) Returns the decoded header, decoded payload, and signature
+parts of the JWS Signature.
+
+Returns an object with three properties, e.g.
+```js
+{ header: { alg: 'HS256' },
+ payload: 'h. jon benjamin',
+ signature: 'YOWPewyGHKu4Y_0M_vtlEnNlqmFOclqp4Hy6hVHfFT4'
+}
+```
+
+## jws.createSign(options)
+
+Returns a new SignStream object.
+
+Options:
+
+* `header` (required)
+* `payload`
+* `key` || `privateKey` || `secret`
+* `encoding` (Optional, defaults to 'utf8')
+
+Other than `header`, all options expect a string or a buffer when the
+value is known ahead of time, or a stream for convenience.
+`key`/`privateKey`/`secret` may also be an object when using an encrypted
+private key, see the [crypto documentation][encrypted-key-docs].
+
+Example:
+
+```js
+
+// This...
+jws.createSign({
+ header: { alg: 'RS256' },
+ privateKey: privateKeyStream,
+ payload: payloadStream,
+}).on('done', function(signature) {
+ // ...
+});
+
+// is equivalent to this:
+const signer = jws.createSign({
+ header: { alg: 'RS256' },
+});
+privateKeyStream.pipe(signer.privateKey);
+payloadStream.pipe(signer.payload);
+signer.on('done', function(signature) {
+ // ...
+});
+```
+
+## jws.createVerify(options)
+
+Returns a new VerifyStream object.
+
+Options:
+
+* `signature`
+* `algorithm`
+* `key` || `publicKey` || `secret`
+* `encoding` (Optional, defaults to 'utf8')
+
+All options expect a string or a buffer when the value is known ahead of
+time, or a stream for convenience.
+
+Example:
+
+```js
+
+// This...
+jws.createVerify({
+ publicKey: pubKeyStream,
+ signature: sigStream,
+}).on('done', function(verified, obj) {
+ // ...
+});
+
+// is equivilant to this:
+const verifier = jws.createVerify();
+pubKeyStream.pipe(verifier.publicKey);
+sigStream.pipe(verifier.signature);
+verifier.on('done', function(verified, obj) {
+ // ...
+});
+```
+
+## Class: SignStream
+
+A `Readable Stream` that emits a single data event (the calculated
+signature) when done.
+
+### Event: 'done'
+`function (signature) { }`
+
+### signer.payload
+
+A `Writable Stream` that expects the JWS payload. Do *not* use if you
+passed a `payload` option to the constructor.
+
+Example:
+
+```js
+payloadStream.pipe(signer.payload);
+```
+
+### signer.secret
signer.key
signer.privateKey
+
+A `Writable Stream`. Expects the JWS secret for HMAC, or the privateKey
+for ECDSA and RSA. Do *not* use if you passed a `secret` or `key` option
+to the constructor.
+
+Example:
+
+```js
+privateKeyStream.pipe(signer.privateKey);
+```
+
+## Class: VerifyStream
+
+This is a `Readable Stream` that emits a single data event, the result
+of whether or not that signature was valid.
+
+### Event: 'done'
+`function (valid, obj) { }`
+
+`valid` is a boolean for whether or not the signature is valid.
+
+### verifier.signature
+
+A `Writable Stream` that expects a JWS Signature. Do *not* use if you
+passed a `signature` option to the constructor.
+
+### verifier.secret
verifier.key
verifier.publicKey
+
+A `Writable Stream` that expects a public key or secret. Do *not* use if you
+passed a `key` or `secret` option to the constructor.
+
+# TODO
+
+* It feels like there should be some convenience options/APIs for
+ defining the algorithm rather than having to define a header object
+ with `{ alg: 'ES512' }` or whatever every time.
+
+* X.509 support, ugh
+
+# License
+
+MIT
+
+```
+Copyright (c) 2013-2015 Brian J. Brennan
+
+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.
+```
+
+[encrypted-key-docs]: https://nodejs.org/api/crypto.html#crypto_sign_sign_private_key_output_format
diff --git a/node_modules/lodash.includes/LICENSE b/node_modules/lodash.includes/LICENSE
new file mode 100644
index 00000000..e0c69d56
--- /dev/null
+++ b/node_modules/lodash.includes/LICENSE
@@ -0,0 +1,47 @@
+Copyright jQuery Foundation and other contributors
+
+Based on Underscore.js, copyright Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/lodash/lodash
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
+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.
+
+====
+
+Copyright and related rights for sample code are waived via CC0. Sample
+code is defined as all source code displayed within the prose of the
+documentation.
+
+CC0: http://creativecommons.org/publicdomain/zero/1.0/
+
+====
+
+Files located in the node_modules and vendor directories are externally
+maintained libraries used by this software which have their own
+licenses; we recommend you read them, as their terms may differ from the
+terms above.
diff --git a/node_modules/lodash.includes/README.md b/node_modules/lodash.includes/README.md
new file mode 100644
index 00000000..26e93775
--- /dev/null
+++ b/node_modules/lodash.includes/README.md
@@ -0,0 +1,18 @@
+# lodash.includes v4.3.0
+
+The [lodash](https://lodash.com/) method `_.includes` exported as a [Node.js](https://nodejs.org/) module.
+
+## Installation
+
+Using npm:
+```bash
+$ {sudo -H} npm i -g npm
+$ npm i --save lodash.includes
+```
+
+In Node.js:
+```js
+var includes = require('lodash.includes');
+```
+
+See the [documentation](https://lodash.com/docs#includes) or [package source](https://github.com/lodash/lodash/blob/4.3.0-npm-packages/lodash.includes) for more details.
diff --git a/node_modules/lodash.includes/index.js b/node_modules/lodash.includes/index.js
new file mode 100644
index 00000000..e88d5338
--- /dev/null
+++ b/node_modules/lodash.includes/index.js
@@ -0,0 +1,745 @@
+/**
+ * lodash (Custom Build)
+ * Build: `lodash modularize exports="npm" -o ./`
+ * Copyright jQuery Foundation and other contributors
+ * Released under MIT license
+ * Based on Underscore.js 1.8.3
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ */
+
+/** Used as references for various `Number` constants. */
+var INFINITY = 1 / 0,
+ MAX_SAFE_INTEGER = 9007199254740991,
+ MAX_INTEGER = 1.7976931348623157e+308,
+ NAN = 0 / 0;
+
+/** `Object#toString` result references. */
+var argsTag = '[object Arguments]',
+ funcTag = '[object Function]',
+ genTag = '[object GeneratorFunction]',
+ stringTag = '[object String]',
+ symbolTag = '[object Symbol]';
+
+/** Used to match leading and trailing whitespace. */
+var reTrim = /^\s+|\s+$/g;
+
+/** Used to detect bad signed hexadecimal string values. */
+var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+
+/** Used to detect binary string values. */
+var reIsBinary = /^0b[01]+$/i;
+
+/** Used to detect octal string values. */
+var reIsOctal = /^0o[0-7]+$/i;
+
+/** Used to detect unsigned integer values. */
+var reIsUint = /^(?:0|[1-9]\d*)$/;
+
+/** Built-in method references without a dependency on `root`. */
+var freeParseInt = parseInt;
+
+/**
+ * A specialized version of `_.map` for arrays without support for iteratee
+ * shorthands.
+ *
+ * @private
+ * @param {Array} [array] The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array ? array.length : 0,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+}
+
+/**
+ * The base implementation of `_.findIndex` and `_.findLastIndex` without
+ * support for iteratee shorthands.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {number} fromIndex The index to search from.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+function baseFindIndex(array, predicate, fromIndex, fromRight) {
+ var length = array.length,
+ index = fromIndex + (fromRight ? 1 : -1);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (predicate(array[index], index, array)) {
+ return index;
+ }
+ }
+ return -1;
+}
+
+/**
+ * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+function baseIndexOf(array, value, fromIndex) {
+ if (value !== value) {
+ return baseFindIndex(array, baseIsNaN, fromIndex);
+ }
+ var index = fromIndex - 1,
+ length = array.length;
+
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+}
+
+/**
+ * The base implementation of `_.isNaN` without support for number objects.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+ */
+function baseIsNaN(value) {
+ return value !== value;
+}
+
+/**
+ * The base implementation of `_.times` without support for iteratee shorthands
+ * or max array length checks.
+ *
+ * @private
+ * @param {number} n The number of times to invoke `iteratee`.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the array of results.
+ */
+function baseTimes(n, iteratee) {
+ var index = -1,
+ result = Array(n);
+
+ while (++index < n) {
+ result[index] = iteratee(index);
+ }
+ return result;
+}
+
+/**
+ * The base implementation of `_.values` and `_.valuesIn` which creates an
+ * array of `object` property values corresponding to the property names
+ * of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the array of property values.
+ */
+function baseValues(object, props) {
+ return arrayMap(props, function(key) {
+ return object[key];
+ });
+}
+
+/**
+ * Creates a unary function that invokes `func` with its argument transformed.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {Function} transform The argument transform.
+ * @returns {Function} Returns the new function.
+ */
+function overArg(func, transform) {
+ return function(arg) {
+ return func(transform(arg));
+ };
+}
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objectToString = objectProto.toString;
+
+/** Built-in value references. */
+var propertyIsEnumerable = objectProto.propertyIsEnumerable;
+
+/* Built-in method references for those with the same name as other `lodash` methods. */
+var nativeKeys = overArg(Object.keys, Object),
+ nativeMax = Math.max;
+
+/**
+ * Creates an array of the enumerable property names of the array-like `value`.
+ *
+ * @private
+ * @param {*} value The value to query.
+ * @param {boolean} inherited Specify returning inherited property names.
+ * @returns {Array} Returns the array of property names.
+ */
+function arrayLikeKeys(value, inherited) {
+ // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
+ // Safari 9 makes `arguments.length` enumerable in strict mode.
+ var result = (isArray(value) || isArguments(value))
+ ? baseTimes(value.length, String)
+ : [];
+
+ var length = result.length,
+ skipIndexes = !!length;
+
+ for (var key in value) {
+ if ((inherited || hasOwnProperty.call(value, key)) &&
+ !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+/**
+ * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+function baseKeys(object) {
+ if (!isPrototype(object)) {
+ return nativeKeys(object);
+ }
+ var result = [];
+ for (var key in Object(object)) {
+ if (hasOwnProperty.call(object, key) && key != 'constructor') {
+ result.push(key);
+ }
+ }
+ return result;
+}
+
+/**
+ * Checks if `value` is a valid array-like index.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
+ */
+function isIndex(value, length) {
+ length = length == null ? MAX_SAFE_INTEGER : length;
+ return !!length &&
+ (typeof value == 'number' || reIsUint.test(value)) &&
+ (value > -1 && value % 1 == 0 && value < length);
+}
+
+/**
+ * Checks if `value` is likely a prototype object.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
+ */
+function isPrototype(value) {
+ var Ctor = value && value.constructor,
+ proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
+
+ return value === proto;
+}
+
+/**
+ * Checks if `value` is in `collection`. If `collection` is a string, it's
+ * checked for a substring of `value`, otherwise
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
+ * is used for equality comparisons. If `fromIndex` is negative, it's used as
+ * the offset from the end of `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to inspect.
+ * @param {*} value The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
+ * @returns {boolean} Returns `true` if `value` is found, else `false`.
+ * @example
+ *
+ * _.includes([1, 2, 3], 1);
+ * // => true
+ *
+ * _.includes([1, 2, 3], 1, 2);
+ * // => false
+ *
+ * _.includes({ 'a': 1, 'b': 2 }, 1);
+ * // => true
+ *
+ * _.includes('abcd', 'bc');
+ * // => true
+ */
+function includes(collection, value, fromIndex, guard) {
+ collection = isArrayLike(collection) ? collection : values(collection);
+ fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
+
+ var length = collection.length;
+ if (fromIndex < 0) {
+ fromIndex = nativeMax(length + fromIndex, 0);
+ }
+ return isString(collection)
+ ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
+ : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
+}
+
+/**
+ * Checks if `value` is likely an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an `arguments` object,
+ * else `false`.
+ * @example
+ *
+ * _.isArguments(function() { return arguments; }());
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+function isArguments(value) {
+ // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
+ return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
+ (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
+}
+
+/**
+ * Checks if `value` is classified as an `Array` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(document.body.children);
+ * // => false
+ *
+ * _.isArray('abc');
+ * // => false
+ *
+ * _.isArray(_.noop);
+ * // => false
+ */
+var isArray = Array.isArray;
+
+/**
+ * Checks if `value` is array-like. A value is considered array-like if it's
+ * not a function and has a `value.length` that's an integer greater than or
+ * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
+ * @example
+ *
+ * _.isArrayLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLike(document.body.children);
+ * // => true
+ *
+ * _.isArrayLike('abc');
+ * // => true
+ *
+ * _.isArrayLike(_.noop);
+ * // => false
+ */
+function isArrayLike(value) {
+ return value != null && isLength(value.length) && !isFunction(value);
+}
+
+/**
+ * This method is like `_.isArrayLike` except that it also checks if `value`
+ * is an object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an array-like object,
+ * else `false`.
+ * @example
+ *
+ * _.isArrayLikeObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isArrayLikeObject(document.body.children);
+ * // => true
+ *
+ * _.isArrayLikeObject('abc');
+ * // => false
+ *
+ * _.isArrayLikeObject(_.noop);
+ * // => false
+ */
+function isArrayLikeObject(value) {
+ return isObjectLike(value) && isArrayLike(value);
+}
+
+/**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a function, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+function isFunction(value) {
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in Safari 8-9 which returns 'object' for typed array and other constructors.
+ var tag = isObject(value) ? objectToString.call(value) : '';
+ return tag == funcTag || tag == genTag;
+}
+
+/**
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ * @example
+ *
+ * _.isLength(3);
+ * // => true
+ *
+ * _.isLength(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isLength(Infinity);
+ * // => false
+ *
+ * _.isLength('3');
+ * // => false
+ */
+function isLength(value) {
+ return typeof value == 'number' &&
+ value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+}
+
+/**
+ * Checks if `value` is the
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(_.noop);
+ * // => true
+ *
+ * _.isObject(null);
+ * // => false
+ */
+function isObject(value) {
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
+}
+
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+/**
+ * Checks if `value` is classified as a `String` primitive or object.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a string, else `false`.
+ * @example
+ *
+ * _.isString('abc');
+ * // => true
+ *
+ * _.isString(1);
+ * // => false
+ */
+function isString(value) {
+ return typeof value == 'string' ||
+ (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag);
+}
+
+/**
+ * Checks if `value` is classified as a `Symbol` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
+ * @example
+ *
+ * _.isSymbol(Symbol.iterator);
+ * // => true
+ *
+ * _.isSymbol('abc');
+ * // => false
+ */
+function isSymbol(value) {
+ return typeof value == 'symbol' ||
+ (isObjectLike(value) && objectToString.call(value) == symbolTag);
+}
+
+/**
+ * Converts `value` to a finite number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.12.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted number.
+ * @example
+ *
+ * _.toFinite(3.2);
+ * // => 3.2
+ *
+ * _.toFinite(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toFinite(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toFinite('3.2');
+ * // => 3.2
+ */
+function toFinite(value) {
+ if (!value) {
+ return value === 0 ? value : 0;
+ }
+ value = toNumber(value);
+ if (value === INFINITY || value === -INFINITY) {
+ var sign = (value < 0 ? -1 : 1);
+ return sign * MAX_INTEGER;
+ }
+ return value === value ? value : 0;
+}
+
+/**
+ * Converts `value` to an integer.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toInteger(3.2);
+ * // => 3
+ *
+ * _.toInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toInteger(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toInteger('3.2');
+ * // => 3
+ */
+function toInteger(value) {
+ var result = toFinite(value),
+ remainder = result % 1;
+
+ return result === result ? (remainder ? result - remainder : result) : 0;
+}
+
+/**
+ * Converts `value` to a number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ * @example
+ *
+ * _.toNumber(3.2);
+ * // => 3.2
+ *
+ * _.toNumber(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toNumber(Infinity);
+ * // => Infinity
+ *
+ * _.toNumber('3.2');
+ * // => 3.2
+ */
+function toNumber(value) {
+ if (typeof value == 'number') {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ if (isObject(value)) {
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
+ value = isObject(other) ? (other + '') : other;
+ }
+ if (typeof value != 'string') {
+ return value === 0 ? value : +value;
+ }
+ value = value.replace(reTrim, '');
+ var isBinary = reIsBinary.test(value);
+ return (isBinary || reIsOctal.test(value))
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
+ : (reIsBadHex.test(value) ? NAN : +value);
+}
+
+/**
+ * Creates an array of the own enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects. See the
+ * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
+ * for more details.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keys(new Foo);
+ * // => ['a', 'b'] (iteration order is not guaranteed)
+ *
+ * _.keys('hi');
+ * // => ['0', '1']
+ */
+function keys(object) {
+ return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
+}
+
+/**
+ * Creates an array of the own enumerable string keyed property values of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @since 0.1.0
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.values(new Foo);
+ * // => [1, 2] (iteration order is not guaranteed)
+ *
+ * _.values('hi');
+ * // => ['h', 'i']
+ */
+function values(object) {
+ return object ? baseValues(object, keys(object)) : [];
+}
+
+module.exports = includes;
diff --git a/node_modules/lodash.includes/package.json b/node_modules/lodash.includes/package.json
new file mode 100644
index 00000000..a02e645d
--- /dev/null
+++ b/node_modules/lodash.includes/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "lodash.includes",
+ "version": "4.3.0",
+ "description": "The lodash method `_.includes` exported as a module.",
+ "homepage": "https://lodash.com/",
+ "icon": "https://lodash.com/icon.svg",
+ "license": "MIT",
+ "keywords": "lodash-modularized, includes",
+ "author": "John-David Dalton (http://allyoucanleet.com/)",
+ "contributors": [
+ "John-David Dalton (http://allyoucanleet.com/)",
+ "Blaine Bublitz (https://github.com/phated)",
+ "Mathias Bynens (https://mathiasbynens.be/)"
+ ],
+ "repository": "lodash/lodash",
+ "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }
+}
diff --git a/node_modules/lodash.isboolean/LICENSE b/node_modules/lodash.isboolean/LICENSE
new file mode 100644
index 00000000..b054ca5a
--- /dev/null
+++ b/node_modules/lodash.isboolean/LICENSE
@@ -0,0 +1,22 @@
+Copyright 2012-2016 The Dojo Foundation
+Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors
+
+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/lodash.isboolean/README.md b/node_modules/lodash.isboolean/README.md
new file mode 100644
index 00000000..b3c476b0
--- /dev/null
+++ b/node_modules/lodash.isboolean/README.md
@@ -0,0 +1,18 @@
+# lodash.isboolean v3.0.3
+
+The [lodash](https://lodash.com/) method `_.isBoolean` exported as a [Node.js](https://nodejs.org/) module.
+
+## Installation
+
+Using npm:
+```bash
+$ {sudo -H} npm i -g npm
+$ npm i --save lodash.isboolean
+```
+
+In Node.js:
+```js
+var isBoolean = require('lodash.isboolean');
+```
+
+See the [documentation](https://lodash.com/docs#isBoolean) or [package source](https://github.com/lodash/lodash/blob/3.0.3-npm-packages/lodash.isboolean) for more details.
diff --git a/node_modules/lodash.isboolean/index.js b/node_modules/lodash.isboolean/index.js
new file mode 100644
index 00000000..23bbabdc
--- /dev/null
+++ b/node_modules/lodash.isboolean/index.js
@@ -0,0 +1,70 @@
+/**
+ * lodash 3.0.3 (Custom Build)
+ * Build: `lodash modularize exports="npm" -o ./`
+ * Copyright 2012-2016 The Dojo Foundation
+ * Based on Underscore.js 1.8.3
+ * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+
+/** `Object#toString` result references. */
+var boolTag = '[object Boolean]';
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/**
+ * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objectToString = objectProto.toString;
+
+/**
+ * Checks if `value` is classified as a boolean primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isBoolean(false);
+ * // => true
+ *
+ * _.isBoolean(null);
+ * // => false
+ */
+function isBoolean(value) {
+ return value === true || value === false ||
+ (isObjectLike(value) && objectToString.call(value) == boolTag);
+}
+
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+module.exports = isBoolean;
diff --git a/node_modules/lodash.isboolean/package.json b/node_modules/lodash.isboolean/package.json
new file mode 100644
index 00000000..01d6e8b9
--- /dev/null
+++ b/node_modules/lodash.isboolean/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "lodash.isboolean",
+ "version": "3.0.3",
+ "description": "The lodash method `_.isBoolean` exported as a module.",
+ "homepage": "https://lodash.com/",
+ "icon": "https://lodash.com/icon.svg",
+ "license": "MIT",
+ "keywords": "lodash-modularized, isboolean",
+ "author": "John-David Dalton (http://allyoucanleet.com/)",
+ "contributors": [
+ "John-David Dalton (http://allyoucanleet.com/)",
+ "Blaine Bublitz (https://github.com/phated)",
+ "Mathias Bynens (https://mathiasbynens.be/)"
+ ],
+ "repository": "lodash/lodash",
+ "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }
+}
diff --git a/node_modules/lodash.isinteger/LICENSE b/node_modules/lodash.isinteger/LICENSE
new file mode 100644
index 00000000..e0c69d56
--- /dev/null
+++ b/node_modules/lodash.isinteger/LICENSE
@@ -0,0 +1,47 @@
+Copyright jQuery Foundation and other contributors
+
+Based on Underscore.js, copyright Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/lodash/lodash
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
+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.
+
+====
+
+Copyright and related rights for sample code are waived via CC0. Sample
+code is defined as all source code displayed within the prose of the
+documentation.
+
+CC0: http://creativecommons.org/publicdomain/zero/1.0/
+
+====
+
+Files located in the node_modules and vendor directories are externally
+maintained libraries used by this software which have their own
+licenses; we recommend you read them, as their terms may differ from the
+terms above.
diff --git a/node_modules/lodash.isinteger/README.md b/node_modules/lodash.isinteger/README.md
new file mode 100644
index 00000000..3a78567b
--- /dev/null
+++ b/node_modules/lodash.isinteger/README.md
@@ -0,0 +1,18 @@
+# lodash.isinteger v4.0.4
+
+The [lodash](https://lodash.com/) method `_.isInteger` exported as a [Node.js](https://nodejs.org/) module.
+
+## Installation
+
+Using npm:
+```bash
+$ {sudo -H} npm i -g npm
+$ npm i --save lodash.isinteger
+```
+
+In Node.js:
+```js
+var isInteger = require('lodash.isinteger');
+```
+
+See the [documentation](https://lodash.com/docs#isInteger) or [package source](https://github.com/lodash/lodash/blob/4.0.4-npm-packages/lodash.isinteger) for more details.
diff --git a/node_modules/lodash.isinteger/index.js b/node_modules/lodash.isinteger/index.js
new file mode 100644
index 00000000..3bf06f00
--- /dev/null
+++ b/node_modules/lodash.isinteger/index.js
@@ -0,0 +1,265 @@
+/**
+ * lodash (Custom Build)
+ * Build: `lodash modularize exports="npm" -o ./`
+ * Copyright jQuery Foundation and other contributors
+ * Released under MIT license
+ * Based on Underscore.js 1.8.3
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ */
+
+/** Used as references for various `Number` constants. */
+var INFINITY = 1 / 0,
+ MAX_INTEGER = 1.7976931348623157e+308,
+ NAN = 0 / 0;
+
+/** `Object#toString` result references. */
+var symbolTag = '[object Symbol]';
+
+/** Used to match leading and trailing whitespace. */
+var reTrim = /^\s+|\s+$/g;
+
+/** Used to detect bad signed hexadecimal string values. */
+var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+
+/** Used to detect binary string values. */
+var reIsBinary = /^0b[01]+$/i;
+
+/** Used to detect octal string values. */
+var reIsOctal = /^0o[0-7]+$/i;
+
+/** Built-in method references without a dependency on `root`. */
+var freeParseInt = parseInt;
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objectToString = objectProto.toString;
+
+/**
+ * Checks if `value` is an integer.
+ *
+ * **Note:** This method is based on
+ * [`Number.isInteger`](https://mdn.io/Number/isInteger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
+ * @example
+ *
+ * _.isInteger(3);
+ * // => true
+ *
+ * _.isInteger(Number.MIN_VALUE);
+ * // => false
+ *
+ * _.isInteger(Infinity);
+ * // => false
+ *
+ * _.isInteger('3');
+ * // => false
+ */
+function isInteger(value) {
+ return typeof value == 'number' && value == toInteger(value);
+}
+
+/**
+ * Checks if `value` is the
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(_.noop);
+ * // => true
+ *
+ * _.isObject(null);
+ * // => false
+ */
+function isObject(value) {
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
+}
+
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+/**
+ * Checks if `value` is classified as a `Symbol` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
+ * @example
+ *
+ * _.isSymbol(Symbol.iterator);
+ * // => true
+ *
+ * _.isSymbol('abc');
+ * // => false
+ */
+function isSymbol(value) {
+ return typeof value == 'symbol' ||
+ (isObjectLike(value) && objectToString.call(value) == symbolTag);
+}
+
+/**
+ * Converts `value` to a finite number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.12.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted number.
+ * @example
+ *
+ * _.toFinite(3.2);
+ * // => 3.2
+ *
+ * _.toFinite(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toFinite(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toFinite('3.2');
+ * // => 3.2
+ */
+function toFinite(value) {
+ if (!value) {
+ return value === 0 ? value : 0;
+ }
+ value = toNumber(value);
+ if (value === INFINITY || value === -INFINITY) {
+ var sign = (value < 0 ? -1 : 1);
+ return sign * MAX_INTEGER;
+ }
+ return value === value ? value : 0;
+}
+
+/**
+ * Converts `value` to an integer.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toInteger(3.2);
+ * // => 3
+ *
+ * _.toInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toInteger(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toInteger('3.2');
+ * // => 3
+ */
+function toInteger(value) {
+ var result = toFinite(value),
+ remainder = result % 1;
+
+ return result === result ? (remainder ? result - remainder : result) : 0;
+}
+
+/**
+ * Converts `value` to a number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ * @example
+ *
+ * _.toNumber(3.2);
+ * // => 3.2
+ *
+ * _.toNumber(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toNumber(Infinity);
+ * // => Infinity
+ *
+ * _.toNumber('3.2');
+ * // => 3.2
+ */
+function toNumber(value) {
+ if (typeof value == 'number') {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ if (isObject(value)) {
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
+ value = isObject(other) ? (other + '') : other;
+ }
+ if (typeof value != 'string') {
+ return value === 0 ? value : +value;
+ }
+ value = value.replace(reTrim, '');
+ var isBinary = reIsBinary.test(value);
+ return (isBinary || reIsOctal.test(value))
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
+ : (reIsBadHex.test(value) ? NAN : +value);
+}
+
+module.exports = isInteger;
diff --git a/node_modules/lodash.isinteger/package.json b/node_modules/lodash.isinteger/package.json
new file mode 100644
index 00000000..92db256f
--- /dev/null
+++ b/node_modules/lodash.isinteger/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "lodash.isinteger",
+ "version": "4.0.4",
+ "description": "The lodash method `_.isInteger` exported as a module.",
+ "homepage": "https://lodash.com/",
+ "icon": "https://lodash.com/icon.svg",
+ "license": "MIT",
+ "keywords": "lodash-modularized, isinteger",
+ "author": "John-David Dalton (http://allyoucanleet.com/)",
+ "contributors": [
+ "John-David Dalton (http://allyoucanleet.com/)",
+ "Blaine Bublitz (https://github.com/phated)",
+ "Mathias Bynens (https://mathiasbynens.be/)"
+ ],
+ "repository": "lodash/lodash",
+ "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }
+}
diff --git a/node_modules/lodash.isnumber/LICENSE b/node_modules/lodash.isnumber/LICENSE
new file mode 100644
index 00000000..b054ca5a
--- /dev/null
+++ b/node_modules/lodash.isnumber/LICENSE
@@ -0,0 +1,22 @@
+Copyright 2012-2016 The Dojo Foundation
+Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors
+
+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/lodash.isnumber/README.md b/node_modules/lodash.isnumber/README.md
new file mode 100644
index 00000000..a1d434dd
--- /dev/null
+++ b/node_modules/lodash.isnumber/README.md
@@ -0,0 +1,18 @@
+# lodash.isnumber v3.0.3
+
+The [lodash](https://lodash.com/) method `_.isNumber` exported as a [Node.js](https://nodejs.org/) module.
+
+## Installation
+
+Using npm:
+```bash
+$ {sudo -H} npm i -g npm
+$ npm i --save lodash.isnumber
+```
+
+In Node.js:
+```js
+var isNumber = require('lodash.isnumber');
+```
+
+See the [documentation](https://lodash.com/docs#isNumber) or [package source](https://github.com/lodash/lodash/blob/3.0.3-npm-packages/lodash.isnumber) for more details.
diff --git a/node_modules/lodash.isnumber/index.js b/node_modules/lodash.isnumber/index.js
new file mode 100644
index 00000000..35a85732
--- /dev/null
+++ b/node_modules/lodash.isnumber/index.js
@@ -0,0 +1,79 @@
+/**
+ * lodash 3.0.3 (Custom Build)
+ * Build: `lodash modularize exports="npm" -o ./`
+ * Copyright 2012-2016 The Dojo Foundation
+ * Based on Underscore.js 1.8.3
+ * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+
+/** `Object#toString` result references. */
+var numberTag = '[object Number]';
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/**
+ * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objectToString = objectProto.toString;
+
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+/**
+ * Checks if `value` is classified as a `Number` primitive or object.
+ *
+ * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified
+ * as numbers, use the `_.isFinite` method.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isNumber(3);
+ * // => true
+ *
+ * _.isNumber(Number.MIN_VALUE);
+ * // => true
+ *
+ * _.isNumber(Infinity);
+ * // => true
+ *
+ * _.isNumber('3');
+ * // => false
+ */
+function isNumber(value) {
+ return typeof value == 'number' ||
+ (isObjectLike(value) && objectToString.call(value) == numberTag);
+}
+
+module.exports = isNumber;
diff --git a/node_modules/lodash.isnumber/package.json b/node_modules/lodash.isnumber/package.json
new file mode 100644
index 00000000..4c33c2a3
--- /dev/null
+++ b/node_modules/lodash.isnumber/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "lodash.isnumber",
+ "version": "3.0.3",
+ "description": "The lodash method `_.isNumber` exported as a module.",
+ "homepage": "https://lodash.com/",
+ "icon": "https://lodash.com/icon.svg",
+ "license": "MIT",
+ "keywords": "lodash-modularized, isnumber",
+ "author": "John-David Dalton (http://allyoucanleet.com/)",
+ "contributors": [
+ "John-David Dalton (http://allyoucanleet.com/)",
+ "Blaine Bublitz (https://github.com/phated)",
+ "Mathias Bynens (https://mathiasbynens.be/)"
+ ],
+ "repository": "lodash/lodash",
+ "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }
+}
diff --git a/node_modules/lodash.isplainobject/LICENSE b/node_modules/lodash.isplainobject/LICENSE
new file mode 100644
index 00000000..e0c69d56
--- /dev/null
+++ b/node_modules/lodash.isplainobject/LICENSE
@@ -0,0 +1,47 @@
+Copyright jQuery Foundation and other contributors
+
+Based on Underscore.js, copyright Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/lodash/lodash
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
+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.
+
+====
+
+Copyright and related rights for sample code are waived via CC0. Sample
+code is defined as all source code displayed within the prose of the
+documentation.
+
+CC0: http://creativecommons.org/publicdomain/zero/1.0/
+
+====
+
+Files located in the node_modules and vendor directories are externally
+maintained libraries used by this software which have their own
+licenses; we recommend you read them, as their terms may differ from the
+terms above.
diff --git a/node_modules/lodash.isplainobject/README.md b/node_modules/lodash.isplainobject/README.md
new file mode 100644
index 00000000..aeefd74d
--- /dev/null
+++ b/node_modules/lodash.isplainobject/README.md
@@ -0,0 +1,18 @@
+# lodash.isplainobject v4.0.6
+
+The [lodash](https://lodash.com/) method `_.isPlainObject` exported as a [Node.js](https://nodejs.org/) module.
+
+## Installation
+
+Using npm:
+```bash
+$ {sudo -H} npm i -g npm
+$ npm i --save lodash.isplainobject
+```
+
+In Node.js:
+```js
+var isPlainObject = require('lodash.isplainobject');
+```
+
+See the [documentation](https://lodash.com/docs#isPlainObject) or [package source](https://github.com/lodash/lodash/blob/4.0.6-npm-packages/lodash.isplainobject) for more details.
diff --git a/node_modules/lodash.isplainobject/index.js b/node_modules/lodash.isplainobject/index.js
new file mode 100644
index 00000000..0f820ee7
--- /dev/null
+++ b/node_modules/lodash.isplainobject/index.js
@@ -0,0 +1,139 @@
+/**
+ * lodash (Custom Build)
+ * Build: `lodash modularize exports="npm" -o ./`
+ * Copyright jQuery Foundation and other contributors
+ * Released under MIT license
+ * Based on Underscore.js 1.8.3
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ */
+
+/** `Object#toString` result references. */
+var objectTag = '[object Object]';
+
+/**
+ * Checks if `value` is a host object in IE < 9.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
+ */
+function isHostObject(value) {
+ // Many host objects are `Object` objects that can coerce to strings
+ // despite having improperly defined `toString` methods.
+ var result = false;
+ if (value != null && typeof value.toString != 'function') {
+ try {
+ result = !!(value + '');
+ } catch (e) {}
+ }
+ return result;
+}
+
+/**
+ * Creates a unary function that invokes `func` with its argument transformed.
+ *
+ * @private
+ * @param {Function} func The function to wrap.
+ * @param {Function} transform The argument transform.
+ * @returns {Function} Returns the new function.
+ */
+function overArg(func, transform) {
+ return function(arg) {
+ return func(transform(arg));
+ };
+}
+
+/** Used for built-in method references. */
+var funcProto = Function.prototype,
+ objectProto = Object.prototype;
+
+/** Used to resolve the decompiled source of functions. */
+var funcToString = funcProto.toString;
+
+/** Used to check objects for own properties. */
+var hasOwnProperty = objectProto.hasOwnProperty;
+
+/** Used to infer the `Object` constructor. */
+var objectCtorString = funcToString.call(Object);
+
+/**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objectToString = objectProto.toString;
+
+/** Built-in value references. */
+var getPrototype = overArg(Object.getPrototypeOf, Object);
+
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+/**
+ * Checks if `value` is a plain object, that is, an object created by the
+ * `Object` constructor or one with a `[[Prototype]]` of `null`.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.8.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * _.isPlainObject(new Foo);
+ * // => false
+ *
+ * _.isPlainObject([1, 2, 3]);
+ * // => false
+ *
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
+ * // => true
+ *
+ * _.isPlainObject(Object.create(null));
+ * // => true
+ */
+function isPlainObject(value) {
+ if (!isObjectLike(value) ||
+ objectToString.call(value) != objectTag || isHostObject(value)) {
+ return false;
+ }
+ var proto = getPrototype(value);
+ if (proto === null) {
+ return true;
+ }
+ var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
+ return (typeof Ctor == 'function' &&
+ Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);
+}
+
+module.exports = isPlainObject;
diff --git a/node_modules/lodash.isplainobject/package.json b/node_modules/lodash.isplainobject/package.json
new file mode 100644
index 00000000..86f6a07e
--- /dev/null
+++ b/node_modules/lodash.isplainobject/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "lodash.isplainobject",
+ "version": "4.0.6",
+ "description": "The lodash method `_.isPlainObject` exported as a module.",
+ "homepage": "https://lodash.com/",
+ "icon": "https://lodash.com/icon.svg",
+ "license": "MIT",
+ "keywords": "lodash-modularized, isplainobject",
+ "author": "John-David Dalton (http://allyoucanleet.com/)",
+ "contributors": [
+ "John-David Dalton (http://allyoucanleet.com/)",
+ "Blaine Bublitz (https://github.com/phated)",
+ "Mathias Bynens (https://mathiasbynens.be/)"
+ ],
+ "repository": "lodash/lodash",
+ "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }
+}
diff --git a/node_modules/lodash.isstring/LICENSE b/node_modules/lodash.isstring/LICENSE
new file mode 100644
index 00000000..b054ca5a
--- /dev/null
+++ b/node_modules/lodash.isstring/LICENSE
@@ -0,0 +1,22 @@
+Copyright 2012-2016 The Dojo Foundation
+Based on Underscore.js, copyright 2009-2016 Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors
+
+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/lodash.isstring/README.md b/node_modules/lodash.isstring/README.md
new file mode 100644
index 00000000..f184029a
--- /dev/null
+++ b/node_modules/lodash.isstring/README.md
@@ -0,0 +1,18 @@
+# lodash.isstring v4.0.1
+
+The [lodash](https://lodash.com/) method `_.isString` exported as a [Node.js](https://nodejs.org/) module.
+
+## Installation
+
+Using npm:
+```bash
+$ {sudo -H} npm i -g npm
+$ npm i --save lodash.isstring
+```
+
+In Node.js:
+```js
+var isString = require('lodash.isstring');
+```
+
+See the [documentation](https://lodash.com/docs#isString) or [package source](https://github.com/lodash/lodash/blob/4.0.1-npm-packages/lodash.isstring) for more details.
diff --git a/node_modules/lodash.isstring/index.js b/node_modules/lodash.isstring/index.js
new file mode 100644
index 00000000..408225c5
--- /dev/null
+++ b/node_modules/lodash.isstring/index.js
@@ -0,0 +1,95 @@
+/**
+ * lodash 4.0.1 (Custom Build)
+ * Build: `lodash modularize exports="npm" -o ./`
+ * Copyright 2012-2016 The Dojo Foundation
+ * Based on Underscore.js 1.8.3
+ * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license
+ */
+
+/** `Object#toString` result references. */
+var stringTag = '[object String]';
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/**
+ * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objectToString = objectProto.toString;
+
+/**
+ * Checks if `value` is classified as an `Array` object.
+ *
+ * @static
+ * @memberOf _
+ * @type Function
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(document.body.children);
+ * // => false
+ *
+ * _.isArray('abc');
+ * // => false
+ *
+ * _.isArray(_.noop);
+ * // => false
+ */
+var isArray = Array.isArray;
+
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+/**
+ * Checks if `value` is classified as a `String` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isString('abc');
+ * // => true
+ *
+ * _.isString(1);
+ * // => false
+ */
+function isString(value) {
+ return typeof value == 'string' ||
+ (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag);
+}
+
+module.exports = isString;
diff --git a/node_modules/lodash.isstring/package.json b/node_modules/lodash.isstring/package.json
new file mode 100644
index 00000000..1331535d
--- /dev/null
+++ b/node_modules/lodash.isstring/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "lodash.isstring",
+ "version": "4.0.1",
+ "description": "The lodash method `_.isString` exported as a module.",
+ "homepage": "https://lodash.com/",
+ "icon": "https://lodash.com/icon.svg",
+ "license": "MIT",
+ "keywords": "lodash-modularized, isstring",
+ "author": "John-David Dalton (http://allyoucanleet.com/)",
+ "contributors": [
+ "John-David Dalton (http://allyoucanleet.com/)",
+ "Blaine Bublitz (https://github.com/phated)",
+ "Mathias Bynens (https://mathiasbynens.be/)"
+ ],
+ "repository": "lodash/lodash",
+ "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }
+}
diff --git a/node_modules/lodash.once/LICENSE b/node_modules/lodash.once/LICENSE
new file mode 100644
index 00000000..e0c69d56
--- /dev/null
+++ b/node_modules/lodash.once/LICENSE
@@ -0,0 +1,47 @@
+Copyright jQuery Foundation and other contributors
+
+Based on Underscore.js, copyright Jeremy Ashkenas,
+DocumentCloud and Investigative Reporters & Editors
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/lodash/lodash
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
+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.
+
+====
+
+Copyright and related rights for sample code are waived via CC0. Sample
+code is defined as all source code displayed within the prose of the
+documentation.
+
+CC0: http://creativecommons.org/publicdomain/zero/1.0/
+
+====
+
+Files located in the node_modules and vendor directories are externally
+maintained libraries used by this software which have their own
+licenses; we recommend you read them, as their terms may differ from the
+terms above.
diff --git a/node_modules/lodash.once/README.md b/node_modules/lodash.once/README.md
new file mode 100644
index 00000000..c4a2f169
--- /dev/null
+++ b/node_modules/lodash.once/README.md
@@ -0,0 +1,18 @@
+# lodash.once v4.1.1
+
+The [lodash](https://lodash.com/) method `_.once` exported as a [Node.js](https://nodejs.org/) module.
+
+## Installation
+
+Using npm:
+```bash
+$ {sudo -H} npm i -g npm
+$ npm i --save lodash.once
+```
+
+In Node.js:
+```js
+var once = require('lodash.once');
+```
+
+See the [documentation](https://lodash.com/docs#once) or [package source](https://github.com/lodash/lodash/blob/4.1.1-npm-packages/lodash.once) for more details.
diff --git a/node_modules/lodash.once/index.js b/node_modules/lodash.once/index.js
new file mode 100644
index 00000000..414ceb33
--- /dev/null
+++ b/node_modules/lodash.once/index.js
@@ -0,0 +1,294 @@
+/**
+ * lodash (Custom Build)
+ * Build: `lodash modularize exports="npm" -o ./`
+ * Copyright jQuery Foundation and other contributors
+ * Released under MIT license
+ * Based on Underscore.js 1.8.3
+ * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ */
+
+/** Used as the `TypeError` message for "Functions" methods. */
+var FUNC_ERROR_TEXT = 'Expected a function';
+
+/** Used as references for various `Number` constants. */
+var INFINITY = 1 / 0,
+ MAX_INTEGER = 1.7976931348623157e+308,
+ NAN = 0 / 0;
+
+/** `Object#toString` result references. */
+var symbolTag = '[object Symbol]';
+
+/** Used to match leading and trailing whitespace. */
+var reTrim = /^\s+|\s+$/g;
+
+/** Used to detect bad signed hexadecimal string values. */
+var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
+
+/** Used to detect binary string values. */
+var reIsBinary = /^0b[01]+$/i;
+
+/** Used to detect octal string values. */
+var reIsOctal = /^0o[0-7]+$/i;
+
+/** Built-in method references without a dependency on `root`. */
+var freeParseInt = parseInt;
+
+/** Used for built-in method references. */
+var objectProto = Object.prototype;
+
+/**
+ * Used to resolve the
+ * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+var objectToString = objectProto.toString;
+
+/**
+ * Creates a function that invokes `func`, with the `this` binding and arguments
+ * of the created function, while it's called less than `n` times. Subsequent
+ * calls to the created function return the result of the last `func` invocation.
+ *
+ * @static
+ * @memberOf _
+ * @since 3.0.0
+ * @category Function
+ * @param {number} n The number of calls at which `func` is no longer invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * jQuery(element).on('click', _.before(5, addContactToList));
+ * // => Allows adding up to 4 contacts to the list.
+ */
+function before(n, func) {
+ var result;
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ n = toInteger(n);
+ return function() {
+ if (--n > 0) {
+ result = func.apply(this, arguments);
+ }
+ if (n <= 1) {
+ func = undefined;
+ }
+ return result;
+ };
+}
+
+/**
+ * Creates a function that is restricted to invoking `func` once. Repeat calls
+ * to the function return the value of the first invocation. The `func` is
+ * invoked with the `this` binding and arguments of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Function
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var initialize = _.once(createApplication);
+ * initialize();
+ * initialize();
+ * // => `createApplication` is invoked once
+ */
+function once(func) {
+ return before(2, func);
+}
+
+/**
+ * Checks if `value` is the
+ * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
+ * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @since 0.1.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(_.noop);
+ * // => true
+ *
+ * _.isObject(null);
+ * // => false
+ */
+function isObject(value) {
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
+}
+
+/**
+ * Checks if `value` is object-like. A value is object-like if it's not `null`
+ * and has a `typeof` result of "object".
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ * @example
+ *
+ * _.isObjectLike({});
+ * // => true
+ *
+ * _.isObjectLike([1, 2, 3]);
+ * // => true
+ *
+ * _.isObjectLike(_.noop);
+ * // => false
+ *
+ * _.isObjectLike(null);
+ * // => false
+ */
+function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+}
+
+/**
+ * Checks if `value` is classified as a `Symbol` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
+ * @example
+ *
+ * _.isSymbol(Symbol.iterator);
+ * // => true
+ *
+ * _.isSymbol('abc');
+ * // => false
+ */
+function isSymbol(value) {
+ return typeof value == 'symbol' ||
+ (isObjectLike(value) && objectToString.call(value) == symbolTag);
+}
+
+/**
+ * Converts `value` to a finite number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.12.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted number.
+ * @example
+ *
+ * _.toFinite(3.2);
+ * // => 3.2
+ *
+ * _.toFinite(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toFinite(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toFinite('3.2');
+ * // => 3.2
+ */
+function toFinite(value) {
+ if (!value) {
+ return value === 0 ? value : 0;
+ }
+ value = toNumber(value);
+ if (value === INFINITY || value === -INFINITY) {
+ var sign = (value < 0 ? -1 : 1);
+ return sign * MAX_INTEGER;
+ }
+ return value === value ? value : 0;
+}
+
+/**
+ * Converts `value` to an integer.
+ *
+ * **Note:** This method is loosely based on
+ * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.toInteger(3.2);
+ * // => 3
+ *
+ * _.toInteger(Number.MIN_VALUE);
+ * // => 0
+ *
+ * _.toInteger(Infinity);
+ * // => 1.7976931348623157e+308
+ *
+ * _.toInteger('3.2');
+ * // => 3
+ */
+function toInteger(value) {
+ var result = toFinite(value),
+ remainder = result % 1;
+
+ return result === result ? (remainder ? result - remainder : result) : 0;
+}
+
+/**
+ * Converts `value` to a number.
+ *
+ * @static
+ * @memberOf _
+ * @since 4.0.0
+ * @category Lang
+ * @param {*} value The value to process.
+ * @returns {number} Returns the number.
+ * @example
+ *
+ * _.toNumber(3.2);
+ * // => 3.2
+ *
+ * _.toNumber(Number.MIN_VALUE);
+ * // => 5e-324
+ *
+ * _.toNumber(Infinity);
+ * // => Infinity
+ *
+ * _.toNumber('3.2');
+ * // => 3.2
+ */
+function toNumber(value) {
+ if (typeof value == 'number') {
+ return value;
+ }
+ if (isSymbol(value)) {
+ return NAN;
+ }
+ if (isObject(value)) {
+ var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
+ value = isObject(other) ? (other + '') : other;
+ }
+ if (typeof value != 'string') {
+ return value === 0 ? value : +value;
+ }
+ value = value.replace(reTrim, '');
+ var isBinary = reIsBinary.test(value);
+ return (isBinary || reIsOctal.test(value))
+ ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
+ : (reIsBadHex.test(value) ? NAN : +value);
+}
+
+module.exports = once;
diff --git a/node_modules/lodash.once/package.json b/node_modules/lodash.once/package.json
new file mode 100644
index 00000000..fae782c2
--- /dev/null
+++ b/node_modules/lodash.once/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "lodash.once",
+ "version": "4.1.1",
+ "description": "The lodash method `_.once` exported as a module.",
+ "homepage": "https://lodash.com/",
+ "icon": "https://lodash.com/icon.svg",
+ "license": "MIT",
+ "keywords": "lodash-modularized, once",
+ "author": "John-David Dalton (http://allyoucanleet.com/)",
+ "contributors": [
+ "John-David Dalton (http://allyoucanleet.com/)",
+ "Blaine Bublitz (https://github.com/phated)",
+ "Mathias Bynens (https://mathiasbynens.be/)"
+ ],
+ "repository": "lodash/lodash",
+ "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }
+}
diff --git a/node_modules/morgan/HISTORY.md b/node_modules/morgan/HISTORY.md
new file mode 100644
index 00000000..817cc713
--- /dev/null
+++ b/node_modules/morgan/HISTORY.md
@@ -0,0 +1,221 @@
+1.10.1 / 2025-07-17
+===================
+
+ * deps: on-headers@~1.1.0
+ - Fix [CVE-2025-7339](https://www.cve.org/CVERecord?id=CVE-2025-7339) ([GHSA-76c9-3jph-rj3q](https://github.com/expressjs/multer/security/advisories/GHSA-76c9-3jph-rj3q))
+
+1.10.0 / 2020-03-20
+===================
+
+ * Add `:total-time` token
+ * Fix trailing space in colored status code for `dev` format
+ * deps: basic-auth@~2.0.1
+ - deps: safe-buffer@5.1.2
+ * deps: depd@~2.0.0
+ - Replace internal `eval` usage with `Function` constructor
+ - Use instance methods on `process` to check for listeners
+ * deps: on-headers@~1.0.2
+ - Fix `res.writeHead` patch missing return value
+
+1.9.1 / 2018-09-10
+==================
+
+ * Fix using special characters in format
+ * deps: depd@~1.1.2
+ - perf: remove argument reassignment
+
+1.9.0 / 2017-09-26
+==================
+
+ * Use `res.headersSent` when available
+ * deps: basic-auth@~2.0.0
+ - Use `safe-buffer` for improved Buffer API
+ * deps: debug@2.6.9
+ * deps: depd@~1.1.1
+ - Remove unnecessary `Buffer` loading
+
+1.8.2 / 2017-05-23
+==================
+
+ * deps: debug@2.6.8
+ - Fix `DEBUG_MAX_ARRAY_LENGTH`
+ - deps: ms@2.0.0
+
+1.8.1 / 2017-02-04
+==================
+
+ * deps: debug@2.6.1
+ - Fix deprecation messages in WebStorm and other editors
+ - Undeprecate `DEBUG_FD` set to `1` or `2`
+
+1.8.0 / 2017-02-04
+==================
+
+ * Fix sending unnecessary `undefined` argument to token functions
+ * deps: basic-auth@~1.1.0
+ * deps: debug@2.6.0
+ - Allow colors in workers
+ - Deprecated `DEBUG_FD` environment variable
+ - Fix error when running under React Native
+ - Use same color for same namespace
+ - deps: ms@0.7.2
+ * perf: enable strict mode in compiled functions
+
+1.7.0 / 2016-02-18
+==================
+
+ * Add `digits` argument to `response-time` token
+ * deps: depd@~1.1.0
+ - Enable strict mode in more places
+ - Support web browser loading
+ * deps: on-headers@~1.0.1
+ - perf: enable strict mode
+
+1.6.1 / 2015-07-03
+==================
+
+ * deps: basic-auth@~1.0.3
+
+1.6.0 / 2015-06-12
+==================
+
+ * Add `morgan.compile(format)` export
+ * Do not color 1xx status codes in `dev` format
+ * Fix `response-time` token to not include response latency
+ * Fix `status` token incorrectly displaying before response in `dev` format
+ * Fix token return values to be `undefined` or a string
+ * Improve representation of multiple headers in `req` and `res` tokens
+ * Use `res.getHeader` in `res` token
+ * deps: basic-auth@~1.0.2
+ - perf: enable strict mode
+ - perf: hoist regular expression
+ - perf: parse with regular expressions
+ - perf: remove argument reassignment
+ * deps: on-finished@~2.3.0
+ - Add defined behavior for HTTP `CONNECT` requests
+ - Add defined behavior for HTTP `Upgrade` requests
+ - deps: ee-first@1.1.1
+ * pref: enable strict mode
+ * pref: reduce function closure scopes
+ * pref: remove dynamic compile on every request for `dev` format
+ * pref: remove an argument reassignment
+ * pref: skip function call without `skip` option
+
+1.5.3 / 2015-05-10
+==================
+
+ * deps: basic-auth@~1.0.1
+ * deps: debug@~2.2.0
+ - deps: ms@0.7.1
+ * deps: depd@~1.0.1
+ * deps: on-finished@~2.2.1
+ - Fix `isFinished(req)` when data buffered
+
+1.5.2 / 2015-03-15
+==================
+
+ * deps: debug@~2.1.3
+ - Fix high intensity foreground color for bold
+ - deps: ms@0.7.0
+
+1.5.1 / 2014-12-31
+==================
+
+ * deps: debug@~2.1.1
+ * deps: on-finished@~2.2.0
+
+1.5.0 / 2014-11-06
+==================
+
+ * Add multiple date formats
+ - `clf` for the common log format
+ - `iso` for the common ISO 8601 date time format
+ - `web` for the common RFC 1123 date time format
+ * Deprecate `buffer` option
+ * Fix date format in `common` and `combined` formats
+ * Fix token arguments to accept values with `"`
+
+1.4.1 / 2014-10-22
+==================
+
+ * deps: on-finished@~2.1.1
+ - Fix handling of pipelined requests
+
+1.4.0 / 2014-10-16
+==================
+
+ * Add `debug` messages
+ * deps: depd@~1.0.0
+
+1.3.2 / 2014-09-27
+==================
+
+ * Fix `req.ip` integration when `immediate: false`
+
+1.3.1 / 2014-09-14
+==================
+
+ * Remove un-used `bytes` dependency
+ * deps: depd@0.4.5
+
+1.3.0 / 2014-09-01
+==================
+
+ * Assert if `format` is not a function or string
+
+1.2.3 / 2014-08-16
+==================
+
+ * deps: on-finished@2.1.0
+
+1.2.2 / 2014-07-27
+==================
+
+ * deps: depd@0.4.4
+ - Work-around v8 generating empty stack traces
+
+1.2.1 / 2014-07-26
+==================
+
+ * deps: depd@0.4.3
+ - Fix exception when global `Error.stackTraceLimit` is too low
+
+1.2.0 / 2014-07-19
+==================
+
+ * Add `:remote-user` token
+ * Add `combined` log format
+ * Add `common` log format
+ * Add `morgan(format, options)` function signature
+ * Deprecate `default` format -- use `combined` format instead
+ * Deprecate not providing a format
+ * Remove non-standard grey color from `dev` format
+
+1.1.1 / 2014-05-20
+==================
+
+ * simplify method to get remote address
+
+1.1.0 / 2014-05-18
+==================
+
+ * "dev" format will use same tokens as other formats
+ * `:response-time` token is now empty when immediate used
+ * `:response-time` token is now monotonic
+ * `:response-time` token has precision to 1 ÎŒs
+ * fix `:status` + immediate output in node.js 0.8
+ * improve `buffer` option to prevent indefinite event loop holding
+ * deps: bytes@1.0.0
+ - add negative support
+
+1.0.1 / 2014-05-04
+==================
+
+ * Make buffer unique per morgan instance
+ * deps: bytes@0.3.0
+ * added terabyte support
+
+1.0.0 / 2014-02-08
+==================
+
+ * Initial release
diff --git a/node_modules/morgan/LICENSE b/node_modules/morgan/LICENSE
new file mode 100644
index 00000000..3fefed9d
--- /dev/null
+++ b/node_modules/morgan/LICENSE
@@ -0,0 +1,23 @@
+(The MIT License)
+
+Copyright (c) 2014 Jonathan Ong
+Copyright (c) 2014-2017 Douglas Christopher Wilson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/morgan/README.md b/node_modules/morgan/README.md
new file mode 100644
index 00000000..cc637979
--- /dev/null
+++ b/node_modules/morgan/README.md
@@ -0,0 +1,436 @@
+# morgan
+
+[![NPM Version][npm-version-image]][npm-url]
+[![NPM Downloads][npm-downloads-image]][npm-url]
+[![Build Status][ci-image]][ci-url]
+[![Coverage Status][coveralls-image]][coveralls-url]
+
+HTTP request logger middleware for node.js
+
+> Named after [Dexter](http://en.wikipedia.org/wiki/Dexter_Morgan), a show you should not watch until completion.
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install morgan
+```
+
+## API
+
+
+
+```js
+var morgan = require('morgan')
+```
+
+### morgan(format, options)
+
+Create a new morgan logger middleware function using the given `format` and `options`.
+The `format` argument may be a string of a predefined name (see below for the names),
+a string of a format string, or a function that will produce a log entry.
+
+The `format` function will be called with three arguments `tokens`, `req`, and `res`,
+where `tokens` is an object with all defined tokens, `req` is the HTTP request and `res`
+is the HTTP response. The function is expected to return a string that will be the log
+line, or `undefined` / `null` to skip logging.
+
+#### Using a predefined format string
+
+
+
+```js
+morgan('tiny')
+```
+
+#### Using format string of predefined tokens
+
+
+
+```js
+morgan(':method :url :status :res[content-length] - :response-time ms')
+```
+
+#### Using a custom format function
+
+
+
+``` js
+morgan(function (tokens, req, res) {
+ return [
+ tokens.method(req, res),
+ tokens.url(req, res),
+ tokens.status(req, res),
+ tokens.res(req, res, 'content-length'), '-',
+ tokens['response-time'](req, res), 'ms'
+ ].join(' ')
+})
+```
+
+#### Options
+
+Morgan accepts these properties in the options object.
+
+##### immediate
+
+Write log line on request instead of response. This means that a requests will
+be logged even if the server crashes, _but data from the response (like the
+response code, content length, etc.) cannot be logged_.
+
+##### skip
+
+Function to determine if logging is skipped, defaults to `false`. This function
+will be called as `skip(req, res)`.
+
+
+
+```js
+// EXAMPLE: only log error responses
+morgan('combined', {
+ skip: function (req, res) { return res.statusCode < 400 }
+})
+```
+
+##### stream
+
+Output stream for writing log lines, defaults to `process.stdout`.
+
+#### Predefined Formats
+
+There are various pre-defined formats provided:
+
+##### combined
+
+Standard Apache combined log output.
+```
+:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"
+# will output
+::1 - - [27/Nov/2024:06:21:42 +0000] "GET /combined HTTP/1.1" 200 2 "-" "curl/8.7.1"
+```
+
+##### common
+
+Standard Apache common log output.
+
+```
+:remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]
+# will output
+::1 - - [27/Nov/2024:06:21:46 +0000] "GET /common HTTP/1.1" 200 2
+```
+
+##### dev
+
+Concise output colored by response status for development use. The `:status`
+token will be colored green for success codes, red for server error codes,
+yellow for client error codes, cyan for redirection codes, and uncolored
+for information codes.
+
+```
+:method :url :status :response-time ms - :res[content-length]
+# will output
+GET /dev 200 0.224 ms - 2
+```
+
+##### short
+
+Shorter than default, also including response time.
+
+```
+:remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms
+# will output
+::1 - GET /short HTTP/1.1 200 2 - 0.283 ms
+```
+
+##### tiny
+
+The minimal output.
+
+```
+:method :url :status :res[content-length] - :response-time ms
+# will output
+GET /tiny 200 2 - 0.188 ms
+```
+
+#### Tokens
+
+##### Creating new tokens
+
+To define a token, simply invoke `morgan.token()` with the name and a callback function.
+This callback function is expected to return a string value. The value returned is then
+available as ":type" in this case:
+
+
+
+```js
+morgan.token('type', function (req, res) { return req.headers['content-type'] })
+```
+
+Calling `morgan.token()` using the same name as an existing token will overwrite that
+token definition.
+
+The token function is expected to be called with the arguments `req` and `res`, representing
+the HTTP request and HTTP response. Additionally, the token can accept further arguments of
+it's choosing to customize behavior.
+
+##### :date[format]
+
+The current date and time in UTC. The available formats are:
+
+ - `clf` for the common log format (`"10/Oct/2000:13:55:36 +0000"`)
+ - `iso` for the common ISO 8601 date time format (`2000-10-10T13:55:36.000Z`)
+ - `web` for the common RFC 1123 date time format (`Tue, 10 Oct 2000 13:55:36 GMT`)
+
+If no format is given, then the default is `web`.
+
+##### :http-version
+
+The HTTP version of the request.
+
+##### :method
+
+The HTTP method of the request.
+
+##### :referrer
+
+The Referrer header of the request. This will use the standard mis-spelled Referer header if exists, otherwise Referrer.
+
+##### :remote-addr
+
+The remote address of the request. This will use `req.ip`, otherwise the standard `req.connection.remoteAddress` value (socket address).
+
+##### :remote-user
+
+The user authenticated as part of Basic auth for the request.
+
+##### :req[header]
+
+The given `header` of the request. If the header is not present, the
+value will be displayed as `"-"` in the log.
+
+##### :res[header]
+
+The given `header` of the response. If the header is not present, the
+value will be displayed as `"-"` in the log.
+
+##### :response-time[digits]
+
+The time between the request coming into `morgan` and when the response
+headers are written, in milliseconds.
+
+The `digits` argument is a number that specifies the number of digits to
+include on the number, defaulting to `3`, which provides microsecond precision.
+
+##### :status
+
+The status code of the response.
+
+If the request/response cycle completes before a response was sent to the
+client (for example, the TCP socket closed prematurely by a client aborting
+the request), then the status will be empty (displayed as `"-"` in the log).
+
+##### :total-time[digits]
+
+The time between the request coming into `morgan` and when the response
+has finished being written out to the connection, in milliseconds.
+
+The `digits` argument is a number that specifies the number of digits to
+include on the number, defaulting to `3`, which provides microsecond precision.
+
+##### :url
+
+The URL of the request. This will use `req.originalUrl` if exists, otherwise `req.url`.
+
+##### :user-agent
+
+The contents of the User-Agent header of the request.
+
+### morgan.compile(format)
+
+Compile a format string into a `format` function for use by `morgan`. A format string
+is a string that represents a single log line and can utilize token syntax.
+Tokens are references by `:token-name`. If tokens accept arguments, they can
+be passed using `[]`, for example: `:token-name[pretty]` would pass the string
+`'pretty'` as an argument to the token `token-name`.
+
+The function returned from `morgan.compile` takes three arguments `tokens`, `req`, and
+`res`, where `tokens` is object with all defined tokens, `req` is the HTTP request and
+`res` is the HTTP response. The function will return a string that will be the log line,
+or `undefined` / `null` to skip logging.
+
+Normally formats are defined using `morgan.format(name, format)`, but for certain
+advanced uses, this compile function is directly available.
+
+## Examples
+
+### express/connect
+
+Sample app that will log all request in the Apache combined format to STDOUT
+
+```js
+var express = require('express')
+var morgan = require('morgan')
+
+var app = express()
+
+app.use(morgan('combined'))
+
+app.get('/', function (req, res) {
+ res.send('hello, world!')
+})
+```
+
+### vanilla http server
+
+Sample app that will log all request in the Apache combined format to STDOUT
+
+```js
+var finalhandler = require('finalhandler')
+var http = require('http')
+var morgan = require('morgan')
+
+// create "middleware"
+var logger = morgan('combined')
+
+http.createServer(function (req, res) {
+ var done = finalhandler(req, res)
+ logger(req, res, function (err) {
+ if (err) return done(err)
+
+ // respond to request
+ res.setHeader('content-type', 'text/plain')
+ res.end('hello, world!')
+ })
+})
+```
+
+### write logs to a file
+
+#### single file
+
+Sample app that will log all requests in the Apache combined format to the file
+`access.log`.
+
+```js
+var express = require('express')
+var fs = require('fs')
+var morgan = require('morgan')
+var path = require('path')
+
+var app = express()
+
+// create a write stream (in append mode)
+var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' })
+
+// setup the logger
+app.use(morgan('combined', { stream: accessLogStream }))
+
+app.get('/', function (req, res) {
+ res.send('hello, world!')
+})
+```
+
+#### log file rotation
+
+Sample app that will log all requests in the Apache combined format to one log
+file per day in the `log/` directory using the
+[rotating-file-stream module](https://www.npmjs.com/package/rotating-file-stream).
+
+```js
+var express = require('express')
+var morgan = require('morgan')
+var path = require('path')
+var rfs = require('rotating-file-stream') // version 2.x
+
+var app = express()
+
+// create a rotating write stream
+var accessLogStream = rfs.createStream('access.log', {
+ interval: '1d', // rotate daily
+ path: path.join(__dirname, 'log')
+})
+
+// setup the logger
+app.use(morgan('combined', { stream: accessLogStream }))
+
+app.get('/', function (req, res) {
+ res.send('hello, world!')
+})
+```
+
+### split / dual logging
+
+The `morgan` middleware can be used as many times as needed, enabling
+combinations like:
+
+ * Log entry on request and one on response
+ * Log all requests to file, but errors to console
+ * ... and more!
+
+Sample app that will log all requests to a file using Apache format, but
+error responses are logged to the console:
+
+```js
+var express = require('express')
+var fs = require('fs')
+var morgan = require('morgan')
+var path = require('path')
+
+var app = express()
+
+// log only 4xx and 5xx responses to console
+app.use(morgan('dev', {
+ skip: function (req, res) { return res.statusCode < 400 }
+}))
+
+// log all requests to access.log
+app.use(morgan('common', {
+ stream: fs.createWriteStream(path.join(__dirname, 'access.log'), { flags: 'a' })
+}))
+
+app.get('/', function (req, res) {
+ res.send('hello, world!')
+})
+```
+
+### use custom token formats
+
+Sample app that will use custom token formats. This adds an ID to all requests and displays it using the `:id` token.
+
+```js
+var express = require('express')
+var morgan = require('morgan')
+var uuid = require('node-uuid')
+
+morgan.token('id', function getId (req) {
+ return req.id
+})
+
+var app = express()
+
+app.use(assignId)
+app.use(morgan(':id :method :url :response-time'))
+
+app.get('/', function (req, res) {
+ res.send('hello, world!')
+})
+
+function assignId (req, res, next) {
+ req.id = uuid.v4()
+ next()
+}
+```
+
+## License
+
+[MIT](LICENSE)
+
+[ci-image]: https://badgen.net/github/checks/expressjs/morgan/master?label=ci
+[ci-url]: https://github.com/expressjs/morgan/actions/workflows/ci.yml
+[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/morgan/master
+[coveralls-url]: https://coveralls.io/r/expressjs/morgan?branch=master
+[npm-downloads-image]: https://badgen.net/npm/dm/morgan
+[npm-url]: https://npmjs.org/package/morgan
+[npm-version-image]: https://badgen.net/npm/v/morgan
diff --git a/node_modules/morgan/index.js b/node_modules/morgan/index.js
new file mode 100644
index 00000000..b33c4f2f
--- /dev/null
+++ b/node_modules/morgan/index.js
@@ -0,0 +1,544 @@
+/*!
+ * morgan
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * Copyright(c) 2014 Jonathan Ong
+ * Copyright(c) 2014-2017 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = morgan
+module.exports.compile = compile
+module.exports.format = format
+module.exports.token = token
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var auth = require('basic-auth')
+var debug = require('debug')('morgan')
+var deprecate = require('depd')('morgan')
+var onFinished = require('on-finished')
+var onHeaders = require('on-headers')
+
+/**
+ * Array of CLF month names.
+ * @private
+ */
+
+var CLF_MONTH = [
+ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
+]
+
+/**
+ * Default log buffer duration.
+ * @private
+ */
+
+var DEFAULT_BUFFER_DURATION = 1000
+
+/**
+ * Create a logger middleware.
+ *
+ * @public
+ * @param {String|Function} format
+ * @param {Object} [options]
+ * @return {Function} middleware
+ */
+
+function morgan (format, options) {
+ var fmt = format
+ var opts = options || {}
+
+ if (format && typeof format === 'object') {
+ opts = format
+ fmt = opts.format || 'default'
+
+ // smart deprecation message
+ deprecate('morgan(options): use morgan(' + (typeof fmt === 'string' ? JSON.stringify(fmt) : 'format') + ', options) instead')
+ }
+
+ if (fmt === undefined) {
+ deprecate('undefined format: specify a format')
+ }
+
+ // output on request instead of response
+ var immediate = opts.immediate
+
+ // check if log entry should be skipped
+ var skip = opts.skip || false
+
+ // format function
+ var formatLine = typeof fmt !== 'function'
+ ? getFormatFunction(fmt)
+ : fmt
+
+ // stream
+ var buffer = opts.buffer
+ var stream = opts.stream || process.stdout
+
+ // buffering support
+ if (buffer) {
+ deprecate('buffer option')
+
+ // flush interval
+ var interval = typeof buffer !== 'number'
+ ? DEFAULT_BUFFER_DURATION
+ : buffer
+
+ // swap the stream
+ stream = createBufferStream(stream, interval)
+ }
+
+ return function logger (req, res, next) {
+ // request data
+ req._startAt = undefined
+ req._startTime = undefined
+ req._remoteAddress = getip(req)
+
+ // response data
+ res._startAt = undefined
+ res._startTime = undefined
+
+ // record request start
+ recordStartTime.call(req)
+
+ function logRequest () {
+ if (skip !== false && skip(req, res)) {
+ debug('skip request')
+ return
+ }
+
+ var line = formatLine(morgan, req, res)
+
+ if (line == null) {
+ debug('skip line')
+ return
+ }
+
+ debug('log request')
+ stream.write(line + '\n')
+ };
+
+ if (immediate) {
+ // immediate log
+ logRequest()
+ } else {
+ // record response start
+ onHeaders(res, recordStartTime)
+
+ // log when response finished
+ onFinished(res, logRequest)
+ }
+
+ next()
+ }
+}
+
+/**
+ * Apache combined log format.
+ */
+
+morgan.format('combined', ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"')
+
+/**
+ * Apache common log format.
+ */
+
+morgan.format('common', ':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length]')
+
+/**
+ * Default format.
+ */
+
+morgan.format('default', ':remote-addr - :remote-user [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer" ":user-agent"')
+deprecate.property(morgan, 'default', 'default format: use combined format')
+
+/**
+ * Short format.
+ */
+
+morgan.format('short', ':remote-addr :remote-user :method :url HTTP/:http-version :status :res[content-length] - :response-time ms')
+
+/**
+ * Tiny format.
+ */
+
+morgan.format('tiny', ':method :url :status :res[content-length] - :response-time ms')
+
+/**
+ * dev (colored)
+ */
+
+morgan.format('dev', function developmentFormatLine (tokens, req, res) {
+ // get the status code if response written
+ var status = headersSent(res)
+ ? res.statusCode
+ : undefined
+
+ // get status color
+ var color = status >= 500 ? 31 // red
+ : status >= 400 ? 33 // yellow
+ : status >= 300 ? 36 // cyan
+ : status >= 200 ? 32 // green
+ : 0 // no color
+
+ // get colored function
+ var fn = developmentFormatLine[color]
+
+ if (!fn) {
+ // compile
+ fn = developmentFormatLine[color] = compile('\x1b[0m:method :url \x1b[' +
+ color + 'm:status\x1b[0m :response-time ms - :res[content-length]\x1b[0m')
+ }
+
+ return fn(tokens, req, res)
+})
+
+/**
+ * request url
+ */
+
+morgan.token('url', function getUrlToken (req) {
+ return req.originalUrl || req.url
+})
+
+/**
+ * request method
+ */
+
+morgan.token('method', function getMethodToken (req) {
+ return req.method
+})
+
+/**
+ * response time in milliseconds
+ */
+
+morgan.token('response-time', function getResponseTimeToken (req, res, digits) {
+ if (!req._startAt || !res._startAt) {
+ // missing request and/or response start time
+ return
+ }
+
+ // calculate diff
+ var ms = (res._startAt[0] - req._startAt[0]) * 1e3 +
+ (res._startAt[1] - req._startAt[1]) * 1e-6
+
+ // return truncated value
+ return ms.toFixed(digits === undefined ? 3 : digits)
+})
+
+/**
+ * total time in milliseconds
+ */
+
+morgan.token('total-time', function getTotalTimeToken (req, res, digits) {
+ if (!req._startAt || !res._startAt) {
+ // missing request and/or response start time
+ return
+ }
+
+ // time elapsed from request start
+ var elapsed = process.hrtime(req._startAt)
+
+ // cover to milliseconds
+ var ms = (elapsed[0] * 1e3) + (elapsed[1] * 1e-6)
+
+ // return truncated value
+ return ms.toFixed(digits === undefined ? 3 : digits)
+})
+
+/**
+ * current date
+ */
+
+morgan.token('date', function getDateToken (req, res, format) {
+ var date = new Date()
+
+ switch (format || 'web') {
+ case 'clf':
+ return clfdate(date)
+ case 'iso':
+ return date.toISOString()
+ case 'web':
+ return date.toUTCString()
+ }
+})
+
+/**
+ * response status code
+ */
+
+morgan.token('status', function getStatusToken (req, res) {
+ return headersSent(res)
+ ? String(res.statusCode)
+ : undefined
+})
+
+/**
+ * normalized referrer
+ */
+
+morgan.token('referrer', function getReferrerToken (req) {
+ return req.headers.referer || req.headers.referrer
+})
+
+/**
+ * remote address
+ */
+
+morgan.token('remote-addr', getip)
+
+/**
+ * remote user
+ */
+
+morgan.token('remote-user', function getRemoteUserToken (req) {
+ // parse basic credentials
+ var credentials = auth(req)
+
+ // return username
+ return credentials
+ ? credentials.name
+ : undefined
+})
+
+/**
+ * HTTP version
+ */
+
+morgan.token('http-version', function getHttpVersionToken (req) {
+ return req.httpVersionMajor + '.' + req.httpVersionMinor
+})
+
+/**
+ * UA string
+ */
+
+morgan.token('user-agent', function getUserAgentToken (req) {
+ return req.headers['user-agent']
+})
+
+/**
+ * request header
+ */
+
+morgan.token('req', function getRequestToken (req, res, field) {
+ // get header
+ var header = req.headers[field.toLowerCase()]
+
+ return Array.isArray(header)
+ ? header.join(', ')
+ : header
+})
+
+/**
+ * response header
+ */
+
+morgan.token('res', function getResponseHeader (req, res, field) {
+ if (!headersSent(res)) {
+ return undefined
+ }
+
+ // get header
+ var header = res.getHeader(field)
+
+ return Array.isArray(header)
+ ? header.join(', ')
+ : header
+})
+
+/**
+ * Format a Date in the common log format.
+ *
+ * @private
+ * @param {Date} dateTime
+ * @return {string}
+ */
+
+function clfdate (dateTime) {
+ var date = dateTime.getUTCDate()
+ var hour = dateTime.getUTCHours()
+ var mins = dateTime.getUTCMinutes()
+ var secs = dateTime.getUTCSeconds()
+ var year = dateTime.getUTCFullYear()
+
+ var month = CLF_MONTH[dateTime.getUTCMonth()]
+
+ return pad2(date) + '/' + month + '/' + year +
+ ':' + pad2(hour) + ':' + pad2(mins) + ':' + pad2(secs) +
+ ' +0000'
+}
+
+/**
+ * Compile a format string into a function.
+ *
+ * @param {string} format
+ * @return {function}
+ * @public
+ */
+
+function compile (format) {
+ if (typeof format !== 'string') {
+ throw new TypeError('argument format must be a string')
+ }
+
+ var fmt = String(JSON.stringify(format))
+ var js = ' "use strict"\n return ' + fmt.replace(/:([-\w]{2,})(?:\[([^\]]+)\])?/g, function (_, name, arg) {
+ var tokenArguments = 'req, res'
+ var tokenFunction = 'tokens[' + String(JSON.stringify(name)) + ']'
+
+ if (arg !== undefined) {
+ tokenArguments += ', ' + String(JSON.stringify(arg))
+ }
+
+ return '" +\n (' + tokenFunction + '(' + tokenArguments + ') || "-") + "'
+ })
+
+ // eslint-disable-next-line no-new-func
+ return new Function('tokens, req, res', js)
+}
+
+/**
+ * Create a basic buffering stream.
+ *
+ * @param {object} stream
+ * @param {number} interval
+ * @public
+ */
+
+function createBufferStream (stream, interval) {
+ var buf = []
+ var timer = null
+
+ // flush function
+ function flush () {
+ timer = null
+ stream.write(buf.join(''))
+ buf.length = 0
+ }
+
+ // write function
+ function write (str) {
+ if (timer === null) {
+ timer = setTimeout(flush, interval)
+ }
+
+ buf.push(str)
+ }
+
+ // return a minimal "stream"
+ return { write: write }
+}
+
+/**
+ * Define a format with the given name.
+ *
+ * @param {string} name
+ * @param {string|function} fmt
+ * @public
+ */
+
+function format (name, fmt) {
+ morgan[name] = fmt
+ return this
+}
+
+/**
+ * Lookup and compile a named format function.
+ *
+ * @param {string} name
+ * @return {function}
+ * @public
+ */
+
+function getFormatFunction (name) {
+ // lookup format
+ var fmt = morgan[name] || name || morgan.default
+
+ // return compiled format
+ return typeof fmt !== 'function'
+ ? compile(fmt)
+ : fmt
+}
+
+/**
+ * Get request IP address.
+ *
+ * @private
+ * @param {IncomingMessage} req
+ * @return {string}
+ */
+
+function getip (req) {
+ return req.ip ||
+ req._remoteAddress ||
+ (req.connection && req.connection.remoteAddress) ||
+ undefined
+}
+
+/**
+ * Determine if the response headers have been sent.
+ *
+ * @param {object} res
+ * @returns {boolean}
+ * @private
+ */
+
+function headersSent (res) {
+ // istanbul ignore next: node.js 0.8 support
+ return typeof res.headersSent !== 'boolean'
+ ? Boolean(res._header)
+ : res.headersSent
+}
+
+/**
+ * Pad number to two digits.
+ *
+ * @private
+ * @param {number} num
+ * @return {string}
+ */
+
+function pad2 (num) {
+ var str = String(num)
+
+ // istanbul ignore next: num is current datetime
+ return (str.length === 1 ? '0' : '') + str
+}
+
+/**
+ * Record the start time.
+ * @private
+ */
+
+function recordStartTime () {
+ this._startAt = process.hrtime()
+ this._startTime = new Date()
+}
+
+/**
+ * Define a token function with the given name,
+ * and callback fn(req, res).
+ *
+ * @param {string} name
+ * @param {function} fn
+ * @public
+ */
+
+function token (name, fn) {
+ morgan[name] = fn
+ return this
+}
diff --git a/node_modules/morgan/node_modules/debug/.coveralls.yml b/node_modules/morgan/node_modules/debug/.coveralls.yml
new file mode 100644
index 00000000..20a70685
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/.coveralls.yml
@@ -0,0 +1 @@
+repo_token: SIAeZjKYlHK74rbcFvNHMUzjRiMpflxve
diff --git a/node_modules/morgan/node_modules/debug/.eslintrc b/node_modules/morgan/node_modules/debug/.eslintrc
new file mode 100644
index 00000000..8a37ae2c
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/.eslintrc
@@ -0,0 +1,11 @@
+{
+ "env": {
+ "browser": true,
+ "node": true
+ },
+ "rules": {
+ "no-console": 0,
+ "no-empty": [1, { "allowEmptyCatch": true }]
+ },
+ "extends": "eslint:recommended"
+}
diff --git a/node_modules/morgan/node_modules/debug/.npmignore b/node_modules/morgan/node_modules/debug/.npmignore
new file mode 100644
index 00000000..5f60eecc
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/.npmignore
@@ -0,0 +1,9 @@
+support
+test
+examples
+example
+*.sock
+dist
+yarn.lock
+coverage
+bower.json
diff --git a/node_modules/morgan/node_modules/debug/.travis.yml b/node_modules/morgan/node_modules/debug/.travis.yml
new file mode 100644
index 00000000..6c6090c3
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/.travis.yml
@@ -0,0 +1,14 @@
+
+language: node_js
+node_js:
+ - "6"
+ - "5"
+ - "4"
+
+install:
+ - make node_modules
+
+script:
+ - make lint
+ - make test
+ - make coveralls
diff --git a/node_modules/morgan/node_modules/debug/CHANGELOG.md b/node_modules/morgan/node_modules/debug/CHANGELOG.md
new file mode 100644
index 00000000..eadaa189
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/CHANGELOG.md
@@ -0,0 +1,362 @@
+
+2.6.9 / 2017-09-22
+==================
+
+ * remove ReDoS regexp in %o formatter (#504)
+
+2.6.8 / 2017-05-18
+==================
+
+ * Fix: Check for undefined on browser globals (#462, @marbemac)
+
+2.6.7 / 2017-05-16
+==================
+
+ * Fix: Update ms to 2.0.0 to fix regular expression denial of service vulnerability (#458, @hubdotcom)
+ * Fix: Inline extend function in node implementation (#452, @dougwilson)
+ * Docs: Fix typo (#455, @msasad)
+
+2.6.5 / 2017-04-27
+==================
+
+ * Fix: null reference check on window.documentElement.style.WebkitAppearance (#447, @thebigredgeek)
+ * Misc: clean up browser reference checks (#447, @thebigredgeek)
+ * Misc: add npm-debug.log to .gitignore (@thebigredgeek)
+
+
+2.6.4 / 2017-04-20
+==================
+
+ * Fix: bug that would occure if process.env.DEBUG is a non-string value. (#444, @LucianBuzzo)
+ * Chore: ignore bower.json in npm installations. (#437, @joaovieira)
+ * Misc: update "ms" to v0.7.3 (@tootallnate)
+
+2.6.3 / 2017-03-13
+==================
+
+ * Fix: Electron reference to `process.env.DEBUG` (#431, @paulcbetts)
+ * Docs: Changelog fix (@thebigredgeek)
+
+2.6.2 / 2017-03-10
+==================
+
+ * Fix: DEBUG_MAX_ARRAY_LENGTH (#420, @slavaGanzin)
+ * Docs: Add backers and sponsors from Open Collective (#422, @piamancini)
+ * Docs: Add Slackin invite badge (@tootallnate)
+
+2.6.1 / 2017-02-10
+==================
+
+ * Fix: Module's `export default` syntax fix for IE8 `Expected identifier` error
+ * Fix: Whitelist DEBUG_FD for values 1 and 2 only (#415, @pi0)
+ * Fix: IE8 "Expected identifier" error (#414, @vgoma)
+ * Fix: Namespaces would not disable once enabled (#409, @musikov)
+
+2.6.0 / 2016-12-28
+==================
+
+ * Fix: added better null pointer checks for browser useColors (@thebigredgeek)
+ * Improvement: removed explicit `window.debug` export (#404, @tootallnate)
+ * Improvement: deprecated `DEBUG_FD` environment variable (#405, @tootallnate)
+
+2.5.2 / 2016-12-25
+==================
+
+ * Fix: reference error on window within webworkers (#393, @KlausTrainer)
+ * Docs: fixed README typo (#391, @lurch)
+ * Docs: added notice about v3 api discussion (@thebigredgeek)
+
+2.5.1 / 2016-12-20
+==================
+
+ * Fix: babel-core compatibility
+
+2.5.0 / 2016-12-20
+==================
+
+ * Fix: wrong reference in bower file (@thebigredgeek)
+ * Fix: webworker compatibility (@thebigredgeek)
+ * Fix: output formatting issue (#388, @kribblo)
+ * Fix: babel-loader compatibility (#383, @escwald)
+ * Misc: removed built asset from repo and publications (@thebigredgeek)
+ * Misc: moved source files to /src (#378, @yamikuronue)
+ * Test: added karma integration and replaced babel with browserify for browser tests (#378, @yamikuronue)
+ * Test: coveralls integration (#378, @yamikuronue)
+ * Docs: simplified language in the opening paragraph (#373, @yamikuronue)
+
+2.4.5 / 2016-12-17
+==================
+
+ * Fix: `navigator` undefined in Rhino (#376, @jochenberger)
+ * Fix: custom log function (#379, @hsiliev)
+ * Improvement: bit of cleanup + linting fixes (@thebigredgeek)
+ * Improvement: rm non-maintainted `dist/` dir (#375, @freewil)
+ * Docs: simplified language in the opening paragraph. (#373, @yamikuronue)
+
+2.4.4 / 2016-12-14
+==================
+
+ * Fix: work around debug being loaded in preload scripts for electron (#368, @paulcbetts)
+
+2.4.3 / 2016-12-14
+==================
+
+ * Fix: navigation.userAgent error for react native (#364, @escwald)
+
+2.4.2 / 2016-12-14
+==================
+
+ * Fix: browser colors (#367, @tootallnate)
+ * Misc: travis ci integration (@thebigredgeek)
+ * Misc: added linting and testing boilerplate with sanity check (@thebigredgeek)
+
+2.4.1 / 2016-12-13
+==================
+
+ * Fix: typo that broke the package (#356)
+
+2.4.0 / 2016-12-13
+==================
+
+ * Fix: bower.json references unbuilt src entry point (#342, @justmatt)
+ * Fix: revert "handle regex special characters" (@tootallnate)
+ * Feature: configurable util.inspect()`options for NodeJS (#327, @tootallnate)
+ * Feature: %O`(big O) pretty-prints objects (#322, @tootallnate)
+ * Improvement: allow colors in workers (#335, @botverse)
+ * Improvement: use same color for same namespace. (#338, @lchenay)
+
+2.3.3 / 2016-11-09
+==================
+
+ * Fix: Catch `JSON.stringify()` errors (#195, Jovan Alleyne)
+ * Fix: Returning `localStorage` saved values (#331, Levi Thomason)
+ * Improvement: Don't create an empty object when no `process` (Nathan Rajlich)
+
+2.3.2 / 2016-11-09
+==================
+
+ * Fix: be super-safe in index.js as well (@TooTallNate)
+ * Fix: should check whether process exists (Tom Newby)
+
+2.3.1 / 2016-11-09
+==================
+
+ * Fix: Added electron compatibility (#324, @paulcbetts)
+ * Improvement: Added performance optimizations (@tootallnate)
+ * Readme: Corrected PowerShell environment variable example (#252, @gimre)
+ * Misc: Removed yarn lock file from source control (#321, @fengmk2)
+
+2.3.0 / 2016-11-07
+==================
+
+ * Fix: Consistent placement of ms diff at end of output (#215, @gorangajic)
+ * Fix: Escaping of regex special characters in namespace strings (#250, @zacronos)
+ * Fix: Fixed bug causing crash on react-native (#282, @vkarpov15)
+ * Feature: Enabled ES6+ compatible import via default export (#212 @bucaran)
+ * Feature: Added %O formatter to reflect Chrome's console.log capability (#279, @oncletom)
+ * Package: Update "ms" to 0.7.2 (#315, @DevSide)
+ * Package: removed superfluous version property from bower.json (#207 @kkirsche)
+ * Readme: fix USE_COLORS to DEBUG_COLORS
+ * Readme: Doc fixes for format string sugar (#269, @mlucool)
+ * Readme: Updated docs for DEBUG_FD and DEBUG_COLORS environment variables (#232, @mattlyons0)
+ * Readme: doc fixes for PowerShell (#271 #243, @exoticknight @unreadable)
+ * Readme: better docs for browser support (#224, @matthewmueller)
+ * Tooling: Added yarn integration for development (#317, @thebigredgeek)
+ * Misc: Renamed History.md to CHANGELOG.md (@thebigredgeek)
+ * Misc: Added license file (#226 #274, @CantemoInternal @sdaitzman)
+ * Misc: Updated contributors (@thebigredgeek)
+
+2.2.0 / 2015-05-09
+==================
+
+ * package: update "ms" to v0.7.1 (#202, @dougwilson)
+ * README: add logging to file example (#193, @DanielOchoa)
+ * README: fixed a typo (#191, @amir-s)
+ * browser: expose `storage` (#190, @stephenmathieson)
+ * Makefile: add a `distclean` target (#189, @stephenmathieson)
+
+2.1.3 / 2015-03-13
+==================
+
+ * Updated stdout/stderr example (#186)
+ * Updated example/stdout.js to match debug current behaviour
+ * Renamed example/stderr.js to stdout.js
+ * Update Readme.md (#184)
+ * replace high intensity foreground color for bold (#182, #183)
+
+2.1.2 / 2015-03-01
+==================
+
+ * dist: recompile
+ * update "ms" to v0.7.0
+ * package: update "browserify" to v9.0.3
+ * component: fix "ms.js" repo location
+ * changed bower package name
+ * updated documentation about using debug in a browser
+ * fix: security error on safari (#167, #168, @yields)
+
+2.1.1 / 2014-12-29
+==================
+
+ * browser: use `typeof` to check for `console` existence
+ * browser: check for `console.log` truthiness (fix IE 8/9)
+ * browser: add support for Chrome apps
+ * Readme: added Windows usage remarks
+ * Add `bower.json` to properly support bower install
+
+2.1.0 / 2014-10-15
+==================
+
+ * node: implement `DEBUG_FD` env variable support
+ * package: update "browserify" to v6.1.0
+ * package: add "license" field to package.json (#135, @panuhorsmalahti)
+
+2.0.0 / 2014-09-01
+==================
+
+ * package: update "browserify" to v5.11.0
+ * node: use stderr rather than stdout for logging (#29, @stephenmathieson)
+
+1.0.4 / 2014-07-15
+==================
+
+ * dist: recompile
+ * example: remove `console.info()` log usage
+ * example: add "Content-Type" UTF-8 header to browser example
+ * browser: place %c marker after the space character
+ * browser: reset the "content" color via `color: inherit`
+ * browser: add colors support for Firefox >= v31
+ * debug: prefer an instance `log()` function over the global one (#119)
+ * Readme: update documentation about styled console logs for FF v31 (#116, @wryk)
+
+1.0.3 / 2014-07-09
+==================
+
+ * Add support for multiple wildcards in namespaces (#122, @seegno)
+ * browser: fix lint
+
+1.0.2 / 2014-06-10
+==================
+
+ * browser: update color palette (#113, @gscottolson)
+ * common: make console logging function configurable (#108, @timoxley)
+ * node: fix %o colors on old node <= 0.8.x
+ * Makefile: find node path using shell/which (#109, @timoxley)
+
+1.0.1 / 2014-06-06
+==================
+
+ * browser: use `removeItem()` to clear localStorage
+ * browser, node: don't set DEBUG if namespaces is undefined (#107, @leedm777)
+ * package: add "contributors" section
+ * node: fix comment typo
+ * README: list authors
+
+1.0.0 / 2014-06-04
+==================
+
+ * make ms diff be global, not be scope
+ * debug: ignore empty strings in enable()
+ * node: make DEBUG_COLORS able to disable coloring
+ * *: export the `colors` array
+ * npmignore: don't publish the `dist` dir
+ * Makefile: refactor to use browserify
+ * package: add "browserify" as a dev dependency
+ * Readme: add Web Inspector Colors section
+ * node: reset terminal color for the debug content
+ * node: map "%o" to `util.inspect()`
+ * browser: map "%j" to `JSON.stringify()`
+ * debug: add custom "formatters"
+ * debug: use "ms" module for humanizing the diff
+ * Readme: add "bash" syntax highlighting
+ * browser: add Firebug color support
+ * browser: add colors for WebKit browsers
+ * node: apply log to `console`
+ * rewrite: abstract common logic for Node & browsers
+ * add .jshintrc file
+
+0.8.1 / 2014-04-14
+==================
+
+ * package: re-add the "component" section
+
+0.8.0 / 2014-03-30
+==================
+
+ * add `enable()` method for nodejs. Closes #27
+ * change from stderr to stdout
+ * remove unnecessary index.js file
+
+0.7.4 / 2013-11-13
+==================
+
+ * remove "browserify" key from package.json (fixes something in browserify)
+
+0.7.3 / 2013-10-30
+==================
+
+ * fix: catch localStorage security error when cookies are blocked (Chrome)
+ * add debug(err) support. Closes #46
+ * add .browser prop to package.json. Closes #42
+
+0.7.2 / 2013-02-06
+==================
+
+ * fix package.json
+ * fix: Mobile Safari (private mode) is broken with debug
+ * fix: Use unicode to send escape character to shell instead of octal to work with strict mode javascript
+
+0.7.1 / 2013-02-05
+==================
+
+ * add repository URL to package.json
+ * add DEBUG_COLORED to force colored output
+ * add browserify support
+ * fix component. Closes #24
+
+0.7.0 / 2012-05-04
+==================
+
+ * Added .component to package.json
+ * Added debug.component.js build
+
+0.6.0 / 2012-03-16
+==================
+
+ * Added support for "-" prefix in DEBUG [Vinay Pulim]
+ * Added `.enabled` flag to the node version [TooTallNate]
+
+0.5.0 / 2012-02-02
+==================
+
+ * Added: humanize diffs. Closes #8
+ * Added `debug.disable()` to the CS variant
+ * Removed padding. Closes #10
+ * Fixed: persist client-side variant again. Closes #9
+
+0.4.0 / 2012-02-01
+==================
+
+ * Added browser variant support for older browsers [TooTallNate]
+ * Added `debug.enable('project:*')` to browser variant [TooTallNate]
+ * Added padding to diff (moved it to the right)
+
+0.3.0 / 2012-01-26
+==================
+
+ * Added millisecond diff when isatty, otherwise UTC string
+
+0.2.0 / 2012-01-22
+==================
+
+ * Added wildcard support
+
+0.1.0 / 2011-12-02
+==================
+
+ * Added: remove colors unless stderr isatty [TooTallNate]
+
+0.0.1 / 2010-01-03
+==================
+
+ * Initial release
diff --git a/node_modules/morgan/node_modules/debug/LICENSE b/node_modules/morgan/node_modules/debug/LICENSE
new file mode 100644
index 00000000..658c933d
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/LICENSE
@@ -0,0 +1,19 @@
+(The MIT License)
+
+Copyright (c) 2014 TJ Holowaychuk
+
+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/morgan/node_modules/debug/Makefile b/node_modules/morgan/node_modules/debug/Makefile
new file mode 100644
index 00000000..584da8bf
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/Makefile
@@ -0,0 +1,50 @@
+# get Makefile directory name: http://stackoverflow.com/a/5982798/376773
+THIS_MAKEFILE_PATH:=$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
+THIS_DIR:=$(shell cd $(dir $(THIS_MAKEFILE_PATH));pwd)
+
+# BIN directory
+BIN := $(THIS_DIR)/node_modules/.bin
+
+# Path
+PATH := node_modules/.bin:$(PATH)
+SHELL := /bin/bash
+
+# applications
+NODE ?= $(shell which node)
+YARN ?= $(shell which yarn)
+PKG ?= $(if $(YARN),$(YARN),$(NODE) $(shell which npm))
+BROWSERIFY ?= $(NODE) $(BIN)/browserify
+
+.FORCE:
+
+install: node_modules
+
+node_modules: package.json
+ @NODE_ENV= $(PKG) install
+ @touch node_modules
+
+lint: .FORCE
+ eslint browser.js debug.js index.js node.js
+
+test-node: .FORCE
+ istanbul cover node_modules/mocha/bin/_mocha -- test/**.js
+
+test-browser: .FORCE
+ mkdir -p dist
+
+ @$(BROWSERIFY) \
+ --standalone debug \
+ . > dist/debug.js
+
+ karma start --single-run
+ rimraf dist
+
+test: .FORCE
+ concurrently \
+ "make test-node" \
+ "make test-browser"
+
+coveralls:
+ cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
+
+.PHONY: all install clean distclean
diff --git a/node_modules/morgan/node_modules/debug/README.md b/node_modules/morgan/node_modules/debug/README.md
new file mode 100644
index 00000000..f67be6b3
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/README.md
@@ -0,0 +1,312 @@
+# debug
+[](https://travis-ci.org/visionmedia/debug) [](https://coveralls.io/github/visionmedia/debug?branch=master) [](https://visionmedia-community-slackin.now.sh/) [](#backers)
+[](#sponsors)
+
+
+
+A tiny node.js debugging utility modelled after node core's debugging technique.
+
+**Discussion around the V3 API is under way [here](https://github.com/visionmedia/debug/issues/370)**
+
+## Installation
+
+```bash
+$ npm install debug
+```
+
+## Usage
+
+`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
+
+Example _app.js_:
+
+```js
+var debug = require('debug')('http')
+ , http = require('http')
+ , name = 'My App';
+
+// fake app
+
+debug('booting %s', name);
+
+http.createServer(function(req, res){
+ debug(req.method + ' ' + req.url);
+ res.end('hello\n');
+}).listen(3000, function(){
+ debug('listening');
+});
+
+// fake worker of some kind
+
+require('./worker');
+```
+
+Example _worker.js_:
+
+```js
+var debug = require('debug')('worker');
+
+setInterval(function(){
+ debug('doing some work');
+}, 1000);
+```
+
+ The __DEBUG__ environment variable is then used to enable these based on space or comma-delimited names. Here are some examples:
+
+ 
+
+ 
+
+#### Windows note
+
+ On Windows the environment variable is set using the `set` command.
+
+ ```cmd
+ set DEBUG=*,-not_this
+ ```
+
+ Note that PowerShell uses different syntax to set environment variables.
+
+ ```cmd
+ $env:DEBUG = "*,-not_this"
+ ```
+
+Then, run the program to be debugged as usual.
+
+## Millisecond diff
+
+ When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
+
+ 
+
+ When stdout is not a TTY, `Date#toUTCString()` is used, making it more useful for logging the debug information as shown below:
+
+ 
+
+## Conventions
+
+ If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser".
+
+## Wildcards
+
+ The `*` character may be used as a wildcard. Suppose for example your library has debuggers named "connect:bodyParser", "connect:compress", "connect:session", instead of listing all three with `DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do `DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
+
+ You can also exclude specific debuggers by prefixing them with a "-" character. For example, `DEBUG=*,-connect:*` would include all debuggers except those starting with "connect:".
+
+## Environment Variables
+
+ When running through Node.js, you can set a few environment variables that will
+ change the behavior of the debug logging:
+
+| Name | Purpose |
+|-----------|-------------------------------------------------|
+| `DEBUG` | Enables/disables specific debugging namespaces. |
+| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
+| `DEBUG_DEPTH` | Object inspection depth. |
+| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
+
+
+ __Note:__ The environment variables beginning with `DEBUG_` end up being
+ converted into an Options object that gets used with `%o`/`%O` formatters.
+ See the Node.js documentation for
+ [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
+ for the complete list.
+
+## Formatters
+
+
+ Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting. Below are the officially supported formatters:
+
+| Formatter | Representation |
+|-----------|----------------|
+| `%O` | Pretty-print an Object on multiple lines. |
+| `%o` | Pretty-print an Object all on a single line. |
+| `%s` | String. |
+| `%d` | Number (both integer and float). |
+| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
+| `%%` | Single percent sign ('%'). This does not consume an argument. |
+
+### Custom formatters
+
+ You can add custom formatters by extending the `debug.formatters` object. For example, if you wanted to add support for rendering a Buffer as hex with `%h`, you could do something like:
+
+```js
+const createDebug = require('debug')
+createDebug.formatters.h = (v) => {
+ return v.toString('hex')
+}
+
+// âŠelsewhere
+const debug = createDebug('foo')
+debug('this is hex: %h', new Buffer('hello world'))
+// foo this is hex: 68656c6c6f20776f726c6421 +0ms
+```
+
+## Browser support
+ You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
+ or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
+ if you don't want to build it yourself.
+
+ Debug's enable state is currently persisted by `localStorage`.
+ Consider the situation shown below where you have `worker:a` and `worker:b`,
+ and wish to debug both. You can enable this using `localStorage.debug`:
+
+```js
+localStorage.debug = 'worker:*'
+```
+
+And then refresh the page.
+
+```js
+a = debug('worker:a');
+b = debug('worker:b');
+
+setInterval(function(){
+ a('doing some work');
+}, 1000);
+
+setInterval(function(){
+ b('doing some work');
+}, 1200);
+```
+
+#### Web Inspector Colors
+
+ Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
+ option. These are WebKit web inspectors, Firefox ([since version
+ 31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
+ and the Firebug plugin for Firefox (any version).
+
+ Colored output looks something like:
+
+ 
+
+
+## Output streams
+
+ By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
+
+Example _stdout.js_:
+
+```js
+var debug = require('debug');
+var error = debug('app:error');
+
+// by default stderr is used
+error('goes to stderr!');
+
+var log = debug('app:log');
+// set this namespace to log via console.log
+log.log = console.log.bind(console); // don't forget to bind to console!
+log('goes to stdout');
+error('still goes to stderr!');
+
+// set all output to go via console.info
+// overrides all per-namespace log settings
+debug.log = console.info.bind(console);
+error('now goes to stdout via console.info');
+log('still goes to stdout, but via console.info now');
+```
+
+
+## Authors
+
+ - TJ Holowaychuk
+ - Nathan Rajlich
+ - Andrew Rhyne
+
+## Backers
+
+Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Sponsors
+
+Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2014-2016 TJ Holowaychuk <tj@vision-media.ca>
+
+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/morgan/node_modules/debug/component.json b/node_modules/morgan/node_modules/debug/component.json
new file mode 100644
index 00000000..9de26410
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/component.json
@@ -0,0 +1,19 @@
+{
+ "name": "debug",
+ "repo": "visionmedia/debug",
+ "description": "small debugging utility",
+ "version": "2.6.9",
+ "keywords": [
+ "debug",
+ "log",
+ "debugger"
+ ],
+ "main": "src/browser.js",
+ "scripts": [
+ "src/browser.js",
+ "src/debug.js"
+ ],
+ "dependencies": {
+ "rauchg/ms.js": "0.7.1"
+ }
+}
diff --git a/node_modules/morgan/node_modules/debug/karma.conf.js b/node_modules/morgan/node_modules/debug/karma.conf.js
new file mode 100644
index 00000000..103a82d1
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/karma.conf.js
@@ -0,0 +1,70 @@
+// Karma configuration
+// Generated on Fri Dec 16 2016 13:09:51 GMT+0000 (UTC)
+
+module.exports = function(config) {
+ config.set({
+
+ // base path that will be used to resolve all patterns (eg. files, exclude)
+ basePath: '',
+
+
+ // frameworks to use
+ // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+ frameworks: ['mocha', 'chai', 'sinon'],
+
+
+ // list of files / patterns to load in the browser
+ files: [
+ 'dist/debug.js',
+ 'test/*spec.js'
+ ],
+
+
+ // list of files to exclude
+ exclude: [
+ 'src/node.js'
+ ],
+
+
+ // preprocess matching files before serving them to the browser
+ // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+ preprocessors: {
+ },
+
+ // test results reporter to use
+ // possible values: 'dots', 'progress'
+ // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+ reporters: ['progress'],
+
+
+ // web server port
+ port: 9876,
+
+
+ // enable / disable colors in the output (reporters and logs)
+ colors: true,
+
+
+ // level of logging
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: true,
+
+
+ // start these browsers
+ // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+ browsers: ['PhantomJS'],
+
+
+ // Continuous Integration mode
+ // if true, Karma captures browsers, runs the tests and exits
+ singleRun: false,
+
+ // Concurrency level
+ // how many browser should be started simultaneous
+ concurrency: Infinity
+ })
+}
diff --git a/node_modules/morgan/node_modules/debug/node.js b/node_modules/morgan/node_modules/debug/node.js
new file mode 100644
index 00000000..7fc36fe6
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/node.js
@@ -0,0 +1 @@
+module.exports = require('./src/node');
diff --git a/node_modules/morgan/node_modules/debug/package.json b/node_modules/morgan/node_modules/debug/package.json
new file mode 100644
index 00000000..dc787ba7
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "debug",
+ "version": "2.6.9",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/visionmedia/debug.git"
+ },
+ "description": "small debugging utility",
+ "keywords": [
+ "debug",
+ "log",
+ "debugger"
+ ],
+ "author": "TJ Holowaychuk ",
+ "contributors": [
+ "Nathan Rajlich (http://n8.io)",
+ "Andrew Rhyne "
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ },
+ "devDependencies": {
+ "browserify": "9.0.3",
+ "chai": "^3.5.0",
+ "concurrently": "^3.1.0",
+ "coveralls": "^2.11.15",
+ "eslint": "^3.12.1",
+ "istanbul": "^0.4.5",
+ "karma": "^1.3.0",
+ "karma-chai": "^0.1.0",
+ "karma-mocha": "^1.3.0",
+ "karma-phantomjs-launcher": "^1.0.2",
+ "karma-sinon": "^1.0.5",
+ "mocha": "^3.2.0",
+ "mocha-lcov-reporter": "^1.2.0",
+ "rimraf": "^2.5.4",
+ "sinon": "^1.17.6",
+ "sinon-chai": "^2.8.0"
+ },
+ "main": "./src/index.js",
+ "browser": "./src/browser.js",
+ "component": {
+ "scripts": {
+ "debug/index.js": "browser.js",
+ "debug/debug.js": "debug.js"
+ }
+ }
+}
diff --git a/node_modules/morgan/node_modules/debug/src/browser.js b/node_modules/morgan/node_modules/debug/src/browser.js
new file mode 100644
index 00000000..71069249
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/src/browser.js
@@ -0,0 +1,185 @@
+/**
+ * This is the web browser implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+exports.storage = 'undefined' != typeof chrome
+ && 'undefined' != typeof chrome.storage
+ ? chrome.storage.local
+ : localstorage();
+
+/**
+ * Colors.
+ */
+
+exports.colors = [
+ 'lightseagreen',
+ 'forestgreen',
+ 'goldenrod',
+ 'dodgerblue',
+ 'darkorchid',
+ 'crimson'
+];
+
+/**
+ * Currently only WebKit-based Web Inspectors, Firefox >= v31,
+ * and the Firebug extension (any Firefox version) are known
+ * to support "%c" CSS customizations.
+ *
+ * TODO: add a `localStorage` variable to explicitly enable/disable colors
+ */
+
+function useColors() {
+ // NB: In an Electron preload script, document will be defined but not fully
+ // initialized. Since we know we're in Chrome, we'll just detect this case
+ // explicitly
+ if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
+ return true;
+ }
+
+ // is webkit? http://stackoverflow.com/a/16459606/376773
+ // document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
+ return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
+ // is firebug? http://stackoverflow.com/a/398120/376773
+ (typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
+ // is firefox >= v31?
+ // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
+ (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
+ // double check webkit in userAgent just in case we are in a worker
+ (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
+}
+
+/**
+ * Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
+ */
+
+exports.formatters.j = function(v) {
+ try {
+ return JSON.stringify(v);
+ } catch (err) {
+ return '[UnexpectedJSONParseError]: ' + err.message;
+ }
+};
+
+
+/**
+ * Colorize log arguments if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+ var useColors = this.useColors;
+
+ args[0] = (useColors ? '%c' : '')
+ + this.namespace
+ + (useColors ? ' %c' : ' ')
+ + args[0]
+ + (useColors ? '%c ' : ' ')
+ + '+' + exports.humanize(this.diff);
+
+ if (!useColors) return;
+
+ var c = 'color: ' + this.color;
+ args.splice(1, 0, c, 'color: inherit')
+
+ // the final "%c" is somewhat tricky, because there could be other
+ // arguments passed either before or after the %c, so we need to
+ // figure out the correct index to insert the CSS into
+ var index = 0;
+ var lastC = 0;
+ args[0].replace(/%[a-zA-Z%]/g, function(match) {
+ if ('%%' === match) return;
+ index++;
+ if ('%c' === match) {
+ // we only are interested in the *last* %c
+ // (the user may have provided their own)
+ lastC = index;
+ }
+ });
+
+ args.splice(lastC, 0, c);
+}
+
+/**
+ * Invokes `console.log()` when available.
+ * No-op when `console.log` is not a "function".
+ *
+ * @api public
+ */
+
+function log() {
+ // this hackery is required for IE8/9, where
+ // the `console.log` function doesn't have 'apply'
+ return 'object' === typeof console
+ && console.log
+ && Function.prototype.apply.call(console.log, console, arguments);
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+ try {
+ if (null == namespaces) {
+ exports.storage.removeItem('debug');
+ } else {
+ exports.storage.debug = namespaces;
+ }
+ } catch(e) {}
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+ var r;
+ try {
+ r = exports.storage.debug;
+ } catch(e) {}
+
+ // If debug isn't set in LS, and we're in Electron, try to load $DEBUG
+ if (!r && typeof process !== 'undefined' && 'env' in process) {
+ r = process.env.DEBUG;
+ }
+
+ return r;
+}
+
+/**
+ * Enable namespaces listed in `localStorage.debug` initially.
+ */
+
+exports.enable(load());
+
+/**
+ * Localstorage attempts to return the localstorage.
+ *
+ * This is necessary because safari throws
+ * when a user disables cookies/localstorage
+ * and you attempt to access it.
+ *
+ * @return {LocalStorage}
+ * @api private
+ */
+
+function localstorage() {
+ try {
+ return window.localStorage;
+ } catch (e) {}
+}
diff --git a/node_modules/morgan/node_modules/debug/src/debug.js b/node_modules/morgan/node_modules/debug/src/debug.js
new file mode 100644
index 00000000..6a5e3fc9
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/src/debug.js
@@ -0,0 +1,202 @@
+
+/**
+ * This is the common logic for both the Node.js and web browser
+ * implementations of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
+exports.coerce = coerce;
+exports.disable = disable;
+exports.enable = enable;
+exports.enabled = enabled;
+exports.humanize = require('ms');
+
+/**
+ * The currently active debug mode names, and names to skip.
+ */
+
+exports.names = [];
+exports.skips = [];
+
+/**
+ * Map of special "%n" handling functions, for the debug "format" argument.
+ *
+ * Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
+ */
+
+exports.formatters = {};
+
+/**
+ * Previous log timestamp.
+ */
+
+var prevTime;
+
+/**
+ * Select a color.
+ * @param {String} namespace
+ * @return {Number}
+ * @api private
+ */
+
+function selectColor(namespace) {
+ var hash = 0, i;
+
+ for (i in namespace) {
+ hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
+ hash |= 0; // Convert to 32bit integer
+ }
+
+ return exports.colors[Math.abs(hash) % exports.colors.length];
+}
+
+/**
+ * Create a debugger with the given `namespace`.
+ *
+ * @param {String} namespace
+ * @return {Function}
+ * @api public
+ */
+
+function createDebug(namespace) {
+
+ function debug() {
+ // disabled?
+ if (!debug.enabled) return;
+
+ var self = debug;
+
+ // set `diff` timestamp
+ var curr = +new Date();
+ var ms = curr - (prevTime || curr);
+ self.diff = ms;
+ self.prev = prevTime;
+ self.curr = curr;
+ prevTime = curr;
+
+ // turn the `arguments` into a proper Array
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; i++) {
+ args[i] = arguments[i];
+ }
+
+ args[0] = exports.coerce(args[0]);
+
+ if ('string' !== typeof args[0]) {
+ // anything else let's inspect with %O
+ args.unshift('%O');
+ }
+
+ // apply any `formatters` transformations
+ var index = 0;
+ args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
+ // if we encounter an escaped % then don't increase the array index
+ if (match === '%%') return match;
+ index++;
+ var formatter = exports.formatters[format];
+ if ('function' === typeof formatter) {
+ var val = args[index];
+ match = formatter.call(self, val);
+
+ // now we need to remove `args[index]` since it's inlined in the `format`
+ args.splice(index, 1);
+ index--;
+ }
+ return match;
+ });
+
+ // apply env-specific formatting (colors, etc.)
+ exports.formatArgs.call(self, args);
+
+ var logFn = debug.log || exports.log || console.log.bind(console);
+ logFn.apply(self, args);
+ }
+
+ debug.namespace = namespace;
+ debug.enabled = exports.enabled(namespace);
+ debug.useColors = exports.useColors();
+ debug.color = selectColor(namespace);
+
+ // env-specific initialization logic for debug instances
+ if ('function' === typeof exports.init) {
+ exports.init(debug);
+ }
+
+ return debug;
+}
+
+/**
+ * Enables a debug mode by namespaces. This can include modes
+ * separated by a colon and wildcards.
+ *
+ * @param {String} namespaces
+ * @api public
+ */
+
+function enable(namespaces) {
+ exports.save(namespaces);
+
+ exports.names = [];
+ exports.skips = [];
+
+ var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
+ var len = split.length;
+
+ for (var i = 0; i < len; i++) {
+ if (!split[i]) continue; // ignore empty strings
+ namespaces = split[i].replace(/\*/g, '.*?');
+ if (namespaces[0] === '-') {
+ exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
+ } else {
+ exports.names.push(new RegExp('^' + namespaces + '$'));
+ }
+ }
+}
+
+/**
+ * Disable debug output.
+ *
+ * @api public
+ */
+
+function disable() {
+ exports.enable('');
+}
+
+/**
+ * Returns true if the given mode name is enabled, false otherwise.
+ *
+ * @param {String} name
+ * @return {Boolean}
+ * @api public
+ */
+
+function enabled(name) {
+ var i, len;
+ for (i = 0, len = exports.skips.length; i < len; i++) {
+ if (exports.skips[i].test(name)) {
+ return false;
+ }
+ }
+ for (i = 0, len = exports.names.length; i < len; i++) {
+ if (exports.names[i].test(name)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Coerce `val`.
+ *
+ * @param {Mixed} val
+ * @return {Mixed}
+ * @api private
+ */
+
+function coerce(val) {
+ if (val instanceof Error) return val.stack || val.message;
+ return val;
+}
diff --git a/node_modules/morgan/node_modules/debug/src/index.js b/node_modules/morgan/node_modules/debug/src/index.js
new file mode 100644
index 00000000..e12cf4d5
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * Detect Electron renderer process, which is node, but we should
+ * treat as a browser.
+ */
+
+if (typeof process !== 'undefined' && process.type === 'renderer') {
+ module.exports = require('./browser.js');
+} else {
+ module.exports = require('./node.js');
+}
diff --git a/node_modules/morgan/node_modules/debug/src/inspector-log.js b/node_modules/morgan/node_modules/debug/src/inspector-log.js
new file mode 100644
index 00000000..60ea6c04
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/src/inspector-log.js
@@ -0,0 +1,15 @@
+module.exports = inspectorLog;
+
+// black hole
+const nullStream = new (require('stream').Writable)();
+nullStream._write = () => {};
+
+/**
+ * Outputs a `console.log()` to the Node.js Inspector console *only*.
+ */
+function inspectorLog() {
+ const stdout = console._stdout;
+ console._stdout = nullStream;
+ console.log.apply(console, arguments);
+ console._stdout = stdout;
+}
diff --git a/node_modules/morgan/node_modules/debug/src/node.js b/node_modules/morgan/node_modules/debug/src/node.js
new file mode 100644
index 00000000..b15109c9
--- /dev/null
+++ b/node_modules/morgan/node_modules/debug/src/node.js
@@ -0,0 +1,248 @@
+/**
+ * Module dependencies.
+ */
+
+var tty = require('tty');
+var util = require('util');
+
+/**
+ * This is the Node.js implementation of `debug()`.
+ *
+ * Expose `debug()` as the module.
+ */
+
+exports = module.exports = require('./debug');
+exports.init = init;
+exports.log = log;
+exports.formatArgs = formatArgs;
+exports.save = save;
+exports.load = load;
+exports.useColors = useColors;
+
+/**
+ * Colors.
+ */
+
+exports.colors = [6, 2, 3, 4, 5, 1];
+
+/**
+ * Build up the default `inspectOpts` object from the environment variables.
+ *
+ * $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
+ */
+
+exports.inspectOpts = Object.keys(process.env).filter(function (key) {
+ return /^debug_/i.test(key);
+}).reduce(function (obj, key) {
+ // camel-case
+ var prop = key
+ .substring(6)
+ .toLowerCase()
+ .replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
+
+ // coerce string value into JS value
+ var val = process.env[key];
+ if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
+ else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
+ else if (val === 'null') val = null;
+ else val = Number(val);
+
+ obj[prop] = val;
+ return obj;
+}, {});
+
+/**
+ * The file descriptor to write the `debug()` calls to.
+ * Set the `DEBUG_FD` env variable to override with another value. i.e.:
+ *
+ * $ DEBUG_FD=3 node script.js 3>debug.log
+ */
+
+var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
+
+if (1 !== fd && 2 !== fd) {
+ util.deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')()
+}
+
+var stream = 1 === fd ? process.stdout :
+ 2 === fd ? process.stderr :
+ createWritableStdioStream(fd);
+
+/**
+ * Is stdout a TTY? Colored output is enabled when `true`.
+ */
+
+function useColors() {
+ return 'colors' in exports.inspectOpts
+ ? Boolean(exports.inspectOpts.colors)
+ : tty.isatty(fd);
+}
+
+/**
+ * Map %o to `util.inspect()`, all on a single line.
+ */
+
+exports.formatters.o = function(v) {
+ this.inspectOpts.colors = this.useColors;
+ return util.inspect(v, this.inspectOpts)
+ .split('\n').map(function(str) {
+ return str.trim()
+ }).join(' ');
+};
+
+/**
+ * Map %o to `util.inspect()`, allowing multiple lines if needed.
+ */
+
+exports.formatters.O = function(v) {
+ this.inspectOpts.colors = this.useColors;
+ return util.inspect(v, this.inspectOpts);
+};
+
+/**
+ * Adds ANSI color escape codes if enabled.
+ *
+ * @api public
+ */
+
+function formatArgs(args) {
+ var name = this.namespace;
+ var useColors = this.useColors;
+
+ if (useColors) {
+ var c = this.color;
+ var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
+
+ args[0] = prefix + args[0].split('\n').join('\n' + prefix);
+ args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
+ } else {
+ args[0] = new Date().toUTCString()
+ + ' ' + name + ' ' + args[0];
+ }
+}
+
+/**
+ * Invokes `util.format()` with the specified arguments and writes to `stream`.
+ */
+
+function log() {
+ return stream.write(util.format.apply(util, arguments) + '\n');
+}
+
+/**
+ * Save `namespaces`.
+ *
+ * @param {String} namespaces
+ * @api private
+ */
+
+function save(namespaces) {
+ if (null == namespaces) {
+ // If you set a process.env field to null or undefined, it gets cast to the
+ // string 'null' or 'undefined'. Just delete instead.
+ delete process.env.DEBUG;
+ } else {
+ process.env.DEBUG = namespaces;
+ }
+}
+
+/**
+ * Load `namespaces`.
+ *
+ * @return {String} returns the previously persisted debug modes
+ * @api private
+ */
+
+function load() {
+ return process.env.DEBUG;
+}
+
+/**
+ * Copied from `node/src/node.js`.
+ *
+ * XXX: It's lame that node doesn't expose this API out-of-the-box. It also
+ * relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
+ */
+
+function createWritableStdioStream (fd) {
+ var stream;
+ var tty_wrap = process.binding('tty_wrap');
+
+ // Note stream._type is used for test-module-load-list.js
+
+ switch (tty_wrap.guessHandleType(fd)) {
+ case 'TTY':
+ stream = new tty.WriteStream(fd);
+ stream._type = 'tty';
+
+ // Hack to have stream not keep the event loop alive.
+ // See https://github.com/joyent/node/issues/1726
+ if (stream._handle && stream._handle.unref) {
+ stream._handle.unref();
+ }
+ break;
+
+ case 'FILE':
+ var fs = require('fs');
+ stream = new fs.SyncWriteStream(fd, { autoClose: false });
+ stream._type = 'fs';
+ break;
+
+ case 'PIPE':
+ case 'TCP':
+ var net = require('net');
+ stream = new net.Socket({
+ fd: fd,
+ readable: false,
+ writable: true
+ });
+
+ // FIXME Should probably have an option in net.Socket to create a
+ // stream from an existing fd which is writable only. But for now
+ // we'll just add this hack and set the `readable` member to false.
+ // Test: ./node test/fixtures/echo.js < /etc/passwd
+ stream.readable = false;
+ stream.read = null;
+ stream._type = 'pipe';
+
+ // FIXME Hack to have stream not keep the event loop alive.
+ // See https://github.com/joyent/node/issues/1726
+ if (stream._handle && stream._handle.unref) {
+ stream._handle.unref();
+ }
+ break;
+
+ default:
+ // Probably an error on in uv_guess_handle()
+ throw new Error('Implement me. Unknown stream file type!');
+ }
+
+ // For supporting legacy API we put the FD here.
+ stream.fd = fd;
+
+ stream._isStdio = true;
+
+ return stream;
+}
+
+/**
+ * Init logic for `debug` instances.
+ *
+ * Create a new `inspectOpts` object in case `useColors` is set
+ * differently for a particular `debug` instance.
+ */
+
+function init (debug) {
+ debug.inspectOpts = {};
+
+ var keys = Object.keys(exports.inspectOpts);
+ for (var i = 0; i < keys.length; i++) {
+ debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
+ }
+}
+
+/**
+ * Enable namespaces listed in `process.env.DEBUG` initially.
+ */
+
+exports.enable(load());
diff --git a/node_modules/morgan/node_modules/ms/index.js b/node_modules/morgan/node_modules/ms/index.js
new file mode 100644
index 00000000..6a522b16
--- /dev/null
+++ b/node_modules/morgan/node_modules/ms/index.js
@@ -0,0 +1,152 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ * - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+ options = options || {};
+ var type = typeof val;
+ if (type === 'string' && val.length > 0) {
+ return parse(val);
+ } else if (type === 'number' && isNaN(val) === false) {
+ return options.long ? fmtLong(val) : fmtShort(val);
+ }
+ throw new Error(
+ 'val is not a non-empty string or a valid number. val=' +
+ JSON.stringify(val)
+ );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+ str = String(str);
+ if (str.length > 100) {
+ return;
+ }
+ var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
+ str
+ );
+ if (!match) {
+ return;
+ }
+ var n = parseFloat(match[1]);
+ var type = (match[2] || 'ms').toLowerCase();
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'yrs':
+ case 'yr':
+ case 'y':
+ return n * y;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * d;
+ case 'hours':
+ case 'hour':
+ case 'hrs':
+ case 'hr':
+ case 'h':
+ return n * h;
+ case 'minutes':
+ case 'minute':
+ case 'mins':
+ case 'min':
+ case 'm':
+ return n * m;
+ case 'seconds':
+ case 'second':
+ case 'secs':
+ case 'sec':
+ case 's':
+ return n * s;
+ case 'milliseconds':
+ case 'millisecond':
+ case 'msecs':
+ case 'msec':
+ case 'ms':
+ return n;
+ default:
+ return undefined;
+ }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+ if (ms >= d) {
+ return Math.round(ms / d) + 'd';
+ }
+ if (ms >= h) {
+ return Math.round(ms / h) + 'h';
+ }
+ if (ms >= m) {
+ return Math.round(ms / m) + 'm';
+ }
+ if (ms >= s) {
+ return Math.round(ms / s) + 's';
+ }
+ return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+ return plural(ms, d, 'day') ||
+ plural(ms, h, 'hour') ||
+ plural(ms, m, 'minute') ||
+ plural(ms, s, 'second') ||
+ ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, n, name) {
+ if (ms < n) {
+ return;
+ }
+ if (ms < n * 1.5) {
+ return Math.floor(ms / n) + ' ' + name;
+ }
+ return Math.ceil(ms / n) + ' ' + name + 's';
+}
diff --git a/node_modules/morgan/node_modules/ms/license.md b/node_modules/morgan/node_modules/ms/license.md
new file mode 100644
index 00000000..69b61253
--- /dev/null
+++ b/node_modules/morgan/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+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/morgan/node_modules/ms/package.json b/node_modules/morgan/node_modules/ms/package.json
new file mode 100644
index 00000000..6a31c81f
--- /dev/null
+++ b/node_modules/morgan/node_modules/ms/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "ms",
+ "version": "2.0.0",
+ "description": "Tiny milisecond conversion utility",
+ "repository": "zeit/ms",
+ "main": "./index",
+ "files": [
+ "index.js"
+ ],
+ "scripts": {
+ "precommit": "lint-staged",
+ "lint": "eslint lib/* bin/*",
+ "test": "mocha tests.js"
+ },
+ "eslintConfig": {
+ "extends": "eslint:recommended",
+ "env": {
+ "node": true,
+ "es6": true
+ }
+ },
+ "lint-staged": {
+ "*.js": [
+ "npm run lint",
+ "prettier --single-quote --write",
+ "git add"
+ ]
+ },
+ "license": "MIT",
+ "devDependencies": {
+ "eslint": "3.19.0",
+ "expect.js": "0.3.1",
+ "husky": "0.13.3",
+ "lint-staged": "3.4.1",
+ "mocha": "3.4.1"
+ }
+}
diff --git a/node_modules/morgan/node_modules/ms/readme.md b/node_modules/morgan/node_modules/ms/readme.md
new file mode 100644
index 00000000..84a9974c
--- /dev/null
+++ b/node_modules/morgan/node_modules/ms/readme.md
@@ -0,0 +1,51 @@
+# ms
+
+[](https://travis-ci.org/zeit/ms)
+[](https://zeit.chat/)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days') // 172800000
+ms('1d') // 86400000
+ms('10h') // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h') // 7200000
+ms('1m') // 60000
+ms('5s') // 5000
+ms('1y') // 31557600000
+ms('100') // 100
+```
+
+### Convert from milliseconds
+
+```js
+ms(60000) // "1m"
+ms(2 * 60000) // "2m"
+ms(ms('10 hours')) // "10h"
+```
+
+### Time format written-out
+
+```js
+ms(60000, { long: true }) // "1 minute"
+ms(2 * 60000, { long: true }) // "2 minutes"
+ms(ms('10 hours'), { long: true }) // "10 hours"
+```
+
+## Features
+
+- Works both in [node](https://nodejs.org) and in the browser.
+- If a number is supplied to `ms`, a string with a unit is returned.
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`).
+- If you pass a string with a number and a valid unit, the number of equivalent ms is returned.
+
+## Caught a bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, node will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/node_modules/morgan/node_modules/on-finished/HISTORY.md b/node_modules/morgan/node_modules/on-finished/HISTORY.md
new file mode 100644
index 00000000..98ff0e99
--- /dev/null
+++ b/node_modules/morgan/node_modules/on-finished/HISTORY.md
@@ -0,0 +1,88 @@
+2.3.0 / 2015-05-26
+==================
+
+ * Add defined behavior for HTTP `CONNECT` requests
+ * Add defined behavior for HTTP `Upgrade` requests
+ * deps: ee-first@1.1.1
+
+2.2.1 / 2015-04-22
+==================
+
+ * Fix `isFinished(req)` when data buffered
+
+2.2.0 / 2014-12-22
+==================
+
+ * Add message object to callback arguments
+
+2.1.1 / 2014-10-22
+==================
+
+ * Fix handling of pipelined requests
+
+2.1.0 / 2014-08-16
+==================
+
+ * Check if `socket` is detached
+ * Return `undefined` for `isFinished` if state unknown
+
+2.0.0 / 2014-08-16
+==================
+
+ * Add `isFinished` function
+ * Move to `jshttp` organization
+ * Remove support for plain socket argument
+ * Rename to `on-finished`
+ * Support both `req` and `res` as arguments
+ * deps: ee-first@1.0.5
+
+1.2.2 / 2014-06-10
+==================
+
+ * Reduce listeners added to emitters
+ - avoids "event emitter leak" warnings when used multiple times on same request
+
+1.2.1 / 2014-06-08
+==================
+
+ * Fix returned value when already finished
+
+1.2.0 / 2014-06-05
+==================
+
+ * Call callback when called on already-finished socket
+
+1.1.4 / 2014-05-27
+==================
+
+ * Support node.js 0.8
+
+1.1.3 / 2014-04-30
+==================
+
+ * Make sure errors passed as instanceof `Error`
+
+1.1.2 / 2014-04-18
+==================
+
+ * Default the `socket` to passed-in object
+
+1.1.1 / 2014-01-16
+==================
+
+ * Rename module to `finished`
+
+1.1.0 / 2013-12-25
+==================
+
+ * Call callback when called on already-errored socket
+
+1.0.1 / 2013-12-20
+==================
+
+ * Actually pass the error to the callback
+
+1.0.0 / 2013-12-20
+==================
+
+ * Initial release
diff --git a/node_modules/morgan/node_modules/on-finished/LICENSE b/node_modules/morgan/node_modules/on-finished/LICENSE
new file mode 100644
index 00000000..5931fd23
--- /dev/null
+++ b/node_modules/morgan/node_modules/on-finished/LICENSE
@@ -0,0 +1,23 @@
+(The MIT License)
+
+Copyright (c) 2013 Jonathan Ong
+Copyright (c) 2014 Douglas Christopher Wilson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/morgan/node_modules/on-finished/README.md b/node_modules/morgan/node_modules/on-finished/README.md
new file mode 100644
index 00000000..a0e11574
--- /dev/null
+++ b/node_modules/morgan/node_modules/on-finished/README.md
@@ -0,0 +1,154 @@
+# on-finished
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Node.js Version][node-version-image]][node-version-url]
+[![Build Status][travis-image]][travis-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+Execute a callback when a HTTP request closes, finishes, or errors.
+
+## Install
+
+```sh
+$ npm install on-finished
+```
+
+## API
+
+```js
+var onFinished = require('on-finished')
+```
+
+### onFinished(res, listener)
+
+Attach a listener to listen for the response to finish. The listener will
+be invoked only once when the response finished. If the response finished
+to an error, the first argument will contain the error. If the response
+has already finished, the listener will be invoked.
+
+Listening to the end of a response would be used to close things associated
+with the response, like open files.
+
+Listener is invoked as `listener(err, res)`.
+
+```js
+onFinished(res, function (err, res) {
+ // clean up open fds, etc.
+ // err contains the error is request error'd
+})
+```
+
+### onFinished(req, listener)
+
+Attach a listener to listen for the request to finish. The listener will
+be invoked only once when the request finished. If the request finished
+to an error, the first argument will contain the error. If the request
+has already finished, the listener will be invoked.
+
+Listening to the end of a request would be used to know when to continue
+after reading the data.
+
+Listener is invoked as `listener(err, req)`.
+
+```js
+var data = ''
+
+req.setEncoding('utf8')
+res.on('data', function (str) {
+ data += str
+})
+
+onFinished(req, function (err, req) {
+ // data is read unless there is err
+})
+```
+
+### onFinished.isFinished(res)
+
+Determine if `res` is already finished. This would be useful to check and
+not even start certain operations if the response has already finished.
+
+### onFinished.isFinished(req)
+
+Determine if `req` is already finished. This would be useful to check and
+not even start certain operations if the request has already finished.
+
+## Special Node.js requests
+
+### HTTP CONNECT method
+
+The meaning of the `CONNECT` method from RFC 7231, section 4.3.6:
+
+> The CONNECT method requests that the recipient establish a tunnel to
+> the destination origin server identified by the request-target and,
+> if successful, thereafter restrict its behavior to blind forwarding
+> of packets, in both directions, until the tunnel is closed. Tunnels
+> are commonly used to create an end-to-end virtual connection, through
+> one or more proxies, which can then be secured using TLS (Transport
+> Layer Security, [RFC5246]).
+
+In Node.js, these request objects come from the `'connect'` event on
+the HTTP server.
+
+When this module is used on a HTTP `CONNECT` request, the request is
+considered "finished" immediately, **due to limitations in the Node.js
+interface**. This means if the `CONNECT` request contains a request entity,
+the request will be considered "finished" even before it has been read.
+
+There is no such thing as a response object to a `CONNECT` request in
+Node.js, so there is no support for for one.
+
+### HTTP Upgrade request
+
+The meaning of the `Upgrade` header from RFC 7230, section 6.1:
+
+> The "Upgrade" header field is intended to provide a simple mechanism
+> for transitioning from HTTP/1.1 to some other protocol on the same
+> connection.
+
+In Node.js, these request objects come from the `'upgrade'` event on
+the HTTP server.
+
+When this module is used on a HTTP request with an `Upgrade` header, the
+request is considered "finished" immediately, **due to limitations in the
+Node.js interface**. This means if the `Upgrade` request contains a request
+entity, the request will be considered "finished" even before it has been
+read.
+
+There is no such thing as a response object to a `Upgrade` request in
+Node.js, so there is no support for for one.
+
+## Example
+
+The following code ensures that file descriptors are always closed
+once the response finishes.
+
+```js
+var destroy = require('destroy')
+var http = require('http')
+var onFinished = require('on-finished')
+
+http.createServer(function onRequest(req, res) {
+ var stream = fs.createReadStream('package.json')
+ stream.pipe(res)
+ onFinished(res, function (err) {
+ destroy(stream)
+ })
+})
+```
+
+## License
+
+[MIT](LICENSE)
+
+[npm-image]: https://img.shields.io/npm/v/on-finished.svg
+[npm-url]: https://npmjs.org/package/on-finished
+[node-version-image]: https://img.shields.io/node/v/on-finished.svg
+[node-version-url]: http://nodejs.org/download/
+[travis-image]: https://img.shields.io/travis/jshttp/on-finished/master.svg
+[travis-url]: https://travis-ci.org/jshttp/on-finished
+[coveralls-image]: https://img.shields.io/coveralls/jshttp/on-finished/master.svg
+[coveralls-url]: https://coveralls.io/r/jshttp/on-finished?branch=master
+[downloads-image]: https://img.shields.io/npm/dm/on-finished.svg
+[downloads-url]: https://npmjs.org/package/on-finished
diff --git a/node_modules/morgan/node_modules/on-finished/index.js b/node_modules/morgan/node_modules/on-finished/index.js
new file mode 100644
index 00000000..9abd98f9
--- /dev/null
+++ b/node_modules/morgan/node_modules/on-finished/index.js
@@ -0,0 +1,196 @@
+/*!
+ * on-finished
+ * Copyright(c) 2013 Jonathan Ong
+ * Copyright(c) 2014 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+'use strict'
+
+/**
+ * Module exports.
+ * @public
+ */
+
+module.exports = onFinished
+module.exports.isFinished = isFinished
+
+/**
+ * Module dependencies.
+ * @private
+ */
+
+var first = require('ee-first')
+
+/**
+ * Variables.
+ * @private
+ */
+
+/* istanbul ignore next */
+var defer = typeof setImmediate === 'function'
+ ? setImmediate
+ : function(fn){ process.nextTick(fn.bind.apply(fn, arguments)) }
+
+/**
+ * Invoke callback when the response has finished, useful for
+ * cleaning up resources afterwards.
+ *
+ * @param {object} msg
+ * @param {function} listener
+ * @return {object}
+ * @public
+ */
+
+function onFinished(msg, listener) {
+ if (isFinished(msg) !== false) {
+ defer(listener, null, msg)
+ return msg
+ }
+
+ // attach the listener to the message
+ attachListener(msg, listener)
+
+ return msg
+}
+
+/**
+ * Determine if message is already finished.
+ *
+ * @param {object} msg
+ * @return {boolean}
+ * @public
+ */
+
+function isFinished(msg) {
+ var socket = msg.socket
+
+ if (typeof msg.finished === 'boolean') {
+ // OutgoingMessage
+ return Boolean(msg.finished || (socket && !socket.writable))
+ }
+
+ if (typeof msg.complete === 'boolean') {
+ // IncomingMessage
+ return Boolean(msg.upgrade || !socket || !socket.readable || (msg.complete && !msg.readable))
+ }
+
+ // don't know
+ return undefined
+}
+
+/**
+ * Attach a finished listener to the message.
+ *
+ * @param {object} msg
+ * @param {function} callback
+ * @private
+ */
+
+function attachFinishedListener(msg, callback) {
+ var eeMsg
+ var eeSocket
+ var finished = false
+
+ function onFinish(error) {
+ eeMsg.cancel()
+ eeSocket.cancel()
+
+ finished = true
+ callback(error)
+ }
+
+ // finished on first message event
+ eeMsg = eeSocket = first([[msg, 'end', 'finish']], onFinish)
+
+ function onSocket(socket) {
+ // remove listener
+ msg.removeListener('socket', onSocket)
+
+ if (finished) return
+ if (eeMsg !== eeSocket) return
+
+ // finished on first socket event
+ eeSocket = first([[socket, 'error', 'close']], onFinish)
+ }
+
+ if (msg.socket) {
+ // socket already assigned
+ onSocket(msg.socket)
+ return
+ }
+
+ // wait for socket to be assigned
+ msg.on('socket', onSocket)
+
+ if (msg.socket === undefined) {
+ // node.js 0.8 patch
+ patchAssignSocket(msg, onSocket)
+ }
+}
+
+/**
+ * Attach the listener to the message.
+ *
+ * @param {object} msg
+ * @return {function}
+ * @private
+ */
+
+function attachListener(msg, listener) {
+ var attached = msg.__onFinished
+
+ // create a private single listener with queue
+ if (!attached || !attached.queue) {
+ attached = msg.__onFinished = createListener(msg)
+ attachFinishedListener(msg, attached)
+ }
+
+ attached.queue.push(listener)
+}
+
+/**
+ * Create listener on message.
+ *
+ * @param {object} msg
+ * @return {function}
+ * @private
+ */
+
+function createListener(msg) {
+ function listener(err) {
+ if (msg.__onFinished === listener) msg.__onFinished = null
+ if (!listener.queue) return
+
+ var queue = listener.queue
+ listener.queue = null
+
+ for (var i = 0; i < queue.length; i++) {
+ queue[i](err, msg)
+ }
+ }
+
+ listener.queue = []
+
+ return listener
+}
+
+/**
+ * Patch ServerResponse.prototype.assignSocket for node.js 0.8.
+ *
+ * @param {ServerResponse} res
+ * @param {function} callback
+ * @private
+ */
+
+function patchAssignSocket(res, callback) {
+ var assignSocket = res.assignSocket
+
+ if (typeof assignSocket !== 'function') return
+
+ // res.on('socket', callback) is broken in 0.8
+ res.assignSocket = function _assignSocket(socket) {
+ assignSocket.call(this, socket)
+ callback(socket)
+ }
+}
diff --git a/node_modules/morgan/node_modules/on-finished/package.json b/node_modules/morgan/node_modules/on-finished/package.json
new file mode 100644
index 00000000..b9df1bd2
--- /dev/null
+++ b/node_modules/morgan/node_modules/on-finished/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "on-finished",
+ "description": "Execute a callback when a request closes, finishes, or errors",
+ "version": "2.3.0",
+ "contributors": [
+ "Douglas Christopher Wilson ",
+ "Jonathan Ong (http://jongleberry.com)"
+ ],
+ "license": "MIT",
+ "repository": "jshttp/on-finished",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "devDependencies": {
+ "istanbul": "0.3.9",
+ "mocha": "2.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "files": [
+ "HISTORY.md",
+ "LICENSE",
+ "index.js"
+ ],
+ "scripts": {
+ "test": "mocha --reporter spec --bail --check-leaks test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/",
+ "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/"
+ }
+}
diff --git a/node_modules/morgan/package.json b/node_modules/morgan/package.json
new file mode 100644
index 00000000..dc5519c3
--- /dev/null
+++ b/node_modules/morgan/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "morgan",
+ "description": "HTTP request logger middleware for node.js",
+ "version": "1.10.1",
+ "contributors": [
+ "Douglas Christopher Wilson ",
+ "Jonathan Ong (http://jongleberry.com)"
+ ],
+ "license": "MIT",
+ "keywords": [
+ "express",
+ "http",
+ "logger",
+ "middleware"
+ ],
+ "repository": "expressjs/morgan",
+ "dependencies": {
+ "basic-auth": "~2.0.1",
+ "debug": "2.6.9",
+ "depd": "~2.0.0",
+ "on-finished": "~2.3.0",
+ "on-headers": "~1.1.0"
+ },
+ "devDependencies": {
+ "eslint": "6.8.0",
+ "eslint-config-standard": "14.1.1",
+ "eslint-plugin-import": "2.20.2",
+ "eslint-plugin-markdown": "1.0.2",
+ "eslint-plugin-node": "11.1.0",
+ "eslint-plugin-promise": "4.2.1",
+ "eslint-plugin-standard": "4.0.1",
+ "mocha": "10.4.0",
+ "nyc": "15.1.0",
+ "split": "1.0.1",
+ "supertest": "4.0.2"
+ },
+ "files": [
+ "LICENSE",
+ "HISTORY.md",
+ "README.md",
+ "index.js"
+ ],
+ "engines": {
+ "node": ">= 0.8.0"
+ },
+ "scripts": {
+ "lint": "eslint --plugin markdown --ext js,md .",
+ "test": "mocha --check-leaks --reporter spec",
+ "test-ci": "nyc --reporter=lcov --reporter=text npm test",
+ "test-cov": "nyc --reporter=html --reporter=text npm test"
+ }
+}
diff --git a/node_modules/node-addon-api/LICENSE.md b/node_modules/node-addon-api/LICENSE.md
new file mode 100644
index 00000000..819d91a5
--- /dev/null
+++ b/node_modules/node-addon-api/LICENSE.md
@@ -0,0 +1,9 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 [Node.js API collaborators](https://github.com/nodejs/node-addon-api#collaborators)
+
+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/node-addon-api/README.md b/node_modules/node-addon-api/README.md
new file mode 100644
index 00000000..89a36ef2
--- /dev/null
+++ b/node_modules/node-addon-api/README.md
@@ -0,0 +1,95 @@
+# **node-addon-api module**
+
+[](https://app.codecov.io/gh/nodejs/node-addon-api/tree/main)
+
+[](https://nodei.co/npm/node-addon-api/) [](https://nodei.co/npm/node-addon-api/)
+
+This module contains **header-only C++ wrapper classes** which simplify
+the use of the C based [Node-API](https://nodejs.org/dist/latest/docs/api/n-api.html)
+provided by Node.js when using C++. It provides a C++ object model
+and exception handling semantics with low overhead.
+
+- [API References](doc/README.md)
+- [Badges](#badges)
+- [Contributing](#contributing)
+- [License](#license)
+
+## API References
+
+API references are available in the [doc](doc/README.md) directory.
+
+
+## Current version: 8.5.0
+
+
+(See [CHANGELOG.md](CHANGELOG.md) for complete Changelog)
+
+node-addon-api is based on [Node-API](https://nodejs.org/api/n-api.html) and supports using different Node-API versions.
+This allows addons built with it to run with Node.js versions which support the targeted Node-API version.
+**However** the node-addon-api support model is to support only the active LTS Node.js versions. This means that
+every year there will be a new major which drops support for the Node.js LTS version which has gone out of service.
+
+The oldest Node.js version supported by the current version of node-addon-api is Node.js 18.x.
+
+## Badges
+
+The use of badges is recommended to indicate the minimum version of Node-API
+required for the module. This helps to determine which Node.js major versions are
+supported. Addon maintainers can consult the [Node-API support matrix][] to determine
+which Node.js versions provide a given Node-API version. The following badges are
+available:
+
+
+
+
+
+
+
+
+
+
+
+
+## Contributing
+
+We love contributions from the community to **node-addon-api**!
+See [CONTRIBUTING.md](CONTRIBUTING.md) for more details on our philosophy around extending this module.
+
+## Team members
+
+### Active
+
+| Name | GitHub Link |
+| ------------------- | ----------------------------------------------------- |
+| Anna Henningsen | [addaleax](https://github.com/addaleax) |
+| Chengzhong Wu | [legendecas](https://github.com/legendecas) |
+| Jack Xia | [JckXia](https://github.com/JckXia) |
+| Kevin Eady | [KevinEady](https://github.com/KevinEady) |
+| Michael Dawson | [mhdawson](https://github.com/mhdawson) |
+| Nicola Del Gobbo | [NickNaso](https://github.com/NickNaso) |
+| Vladimir Morozov | [vmoroz](https://github.com/vmoroz) |
+
+
+
+Emeritus
+
+### Emeritus
+
+| Name | GitHub Link |
+| ------------------- | ----------------------------------------------------- |
+| Arunesh Chandra | [aruneshchandra](https://github.com/aruneshchandra) |
+| Benjamin Byholm | [kkoopa](https://github.com/kkoopa) |
+| Gabriel Schulhof | [gabrielschulhof](https://github.com/gabrielschulhof) |
+| Hitesh Kanwathirtha | [digitalinfinity](https://github.com/digitalinfinity) |
+| Jason Ginchereau | [jasongin](https://github.com/jasongin) |
+| Jim Schlight | [jschlight](https://github.com/jschlight) |
+| Sampson Gao | [sampsongao](https://github.com/sampsongao) |
+| Taylor Woll | [boingoing](https://github.com/boingoing) |
+
+
+
+## License
+
+Licensed under [MIT](./LICENSE.md)
+
+[Node-API support matrix]: https://nodejs.org/dist/latest/docs/api/n-api.html#node-api-version-matrix
diff --git a/node_modules/node-addon-api/common.gypi b/node_modules/node-addon-api/common.gypi
new file mode 100644
index 00000000..e594f14f
--- /dev/null
+++ b/node_modules/node-addon-api/common.gypi
@@ -0,0 +1,21 @@
+{
+ 'variables': {
+ 'NAPI_VERSION%': "
+inline PropertyDescriptor PropertyDescriptor::Accessor(
+ const char* utf8name,
+ Getter getter,
+ napi_property_attributes attributes,
+ void* /*data*/) {
+ using CbData = details::CallbackData;
+ // TODO: Delete when the function is destroyed
+ auto callbackData = new CbData({getter, nullptr});
+
+ return PropertyDescriptor({utf8name,
+ nullptr,
+ nullptr,
+ CbData::Wrapper,
+ nullptr,
+ nullptr,
+ attributes,
+ callbackData});
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Accessor(
+ const std::string& utf8name,
+ Getter getter,
+ napi_property_attributes attributes,
+ void* data) {
+ return Accessor(utf8name.c_str(), getter, attributes, data);
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Accessor(
+ napi_value name,
+ Getter getter,
+ napi_property_attributes attributes,
+ void* /*data*/) {
+ using CbData = details::CallbackData;
+ // TODO: Delete when the function is destroyed
+ auto callbackData = new CbData({getter, nullptr});
+
+ return PropertyDescriptor({nullptr,
+ name,
+ nullptr,
+ CbData::Wrapper,
+ nullptr,
+ nullptr,
+ attributes,
+ callbackData});
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Accessor(
+ Name name, Getter getter, napi_property_attributes attributes, void* data) {
+ napi_value nameValue = name;
+ return PropertyDescriptor::Accessor(nameValue, getter, attributes, data);
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Accessor(
+ const char* utf8name,
+ Getter getter,
+ Setter setter,
+ napi_property_attributes attributes,
+ void* /*data*/) {
+ using CbData = details::AccessorCallbackData;
+ // TODO: Delete when the function is destroyed
+ auto callbackData = new CbData({getter, setter, nullptr});
+
+ return PropertyDescriptor({utf8name,
+ nullptr,
+ nullptr,
+ CbData::GetterWrapper,
+ CbData::SetterWrapper,
+ nullptr,
+ attributes,
+ callbackData});
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Accessor(
+ const std::string& utf8name,
+ Getter getter,
+ Setter setter,
+ napi_property_attributes attributes,
+ void* data) {
+ return Accessor(utf8name.c_str(), getter, setter, attributes, data);
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Accessor(
+ napi_value name,
+ Getter getter,
+ Setter setter,
+ napi_property_attributes attributes,
+ void* /*data*/) {
+ using CbData = details::AccessorCallbackData;
+ // TODO: Delete when the function is destroyed
+ auto callbackData = new CbData({getter, setter, nullptr});
+
+ return PropertyDescriptor({nullptr,
+ name,
+ nullptr,
+ CbData::GetterWrapper,
+ CbData::SetterWrapper,
+ nullptr,
+ attributes,
+ callbackData});
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Accessor(
+ Name name,
+ Getter getter,
+ Setter setter,
+ napi_property_attributes attributes,
+ void* data) {
+ napi_value nameValue = name;
+ return PropertyDescriptor::Accessor(
+ nameValue, getter, setter, attributes, data);
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Function(
+ const char* utf8name,
+ Callable cb,
+ napi_property_attributes attributes,
+ void* /*data*/) {
+ using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr)));
+ using CbData = details::CallbackData;
+ // TODO: Delete when the function is destroyed
+ auto callbackData = new CbData({cb, nullptr});
+
+ return PropertyDescriptor({utf8name,
+ nullptr,
+ CbData::Wrapper,
+ nullptr,
+ nullptr,
+ nullptr,
+ attributes,
+ callbackData});
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Function(
+ const std::string& utf8name,
+ Callable cb,
+ napi_property_attributes attributes,
+ void* data) {
+ return Function(utf8name.c_str(), cb, attributes, data);
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Function(
+ napi_value name,
+ Callable cb,
+ napi_property_attributes attributes,
+ void* /*data*/) {
+ using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr)));
+ using CbData = details::CallbackData;
+ // TODO: Delete when the function is destroyed
+ auto callbackData = new CbData({cb, nullptr});
+
+ return PropertyDescriptor({nullptr,
+ name,
+ CbData::Wrapper,
+ nullptr,
+ nullptr,
+ nullptr,
+ attributes,
+ callbackData});
+}
+
+template
+inline PropertyDescriptor PropertyDescriptor::Function(
+ Name name, Callable cb, napi_property_attributes attributes, void* data) {
+ napi_value nameValue = name;
+ return PropertyDescriptor::Function(nameValue, cb, attributes, data);
+}
+
+#endif // !SRC_NAPI_INL_DEPRECATED_H_
diff --git a/node_modules/node-addon-api/napi-inl.h b/node_modules/node-addon-api/napi-inl.h
new file mode 100644
index 00000000..54651c1b
--- /dev/null
+++ b/node_modules/node-addon-api/napi-inl.h
@@ -0,0 +1,7033 @@
+#ifndef SRC_NAPI_INL_H_
+#define SRC_NAPI_INL_H_
+
+////////////////////////////////////////////////////////////////////////////////
+// Node-API C++ Wrapper Classes
+//
+// Inline header-only implementations for "Node-API" ABI-stable C APIs for
+// Node.js.
+////////////////////////////////////////////////////////////////////////////////
+
+// Note: Do not include this file directly! Include "napi.h" instead.
+// This should be a no-op and is intended for better IDE integration.
+#include "napi.h"
+
+#include
+#include
+#include
+#if NAPI_HAS_THREADS
+#include
+#endif // NAPI_HAS_THREADS
+#include
+#include
+
+namespace Napi {
+
+#ifdef NAPI_CPP_CUSTOM_NAMESPACE
+namespace NAPI_CPP_CUSTOM_NAMESPACE {
+#endif
+
+// Helpers to handle functions exposed from C++ and internal constants.
+namespace details {
+
+// New napi_status constants not yet available in all supported versions of
+// Node.js releases. Only necessary when they are used in napi.h and napi-inl.h.
+constexpr int napi_no_external_buffers_allowed = 22;
+
+template
+inline void default_basic_finalizer(node_addon_api_basic_env /*env*/,
+ void* data,
+ void* /*hint*/) {
+ delete static_cast(data);
+}
+
+// Attach a data item to an object and delete it when the object gets
+// garbage-collected.
+// TODO: Replace this code with `napi_add_finalizer()` whenever it becomes
+// available on all supported versions of Node.js.
+template <
+ typename FreeType,
+ node_addon_api_basic_finalize finalizer = default_basic_finalizer>
+inline napi_status AttachData(napi_env env,
+ napi_value obj,
+ FreeType* data,
+ void* hint = nullptr) {
+ napi_status status;
+#if (NAPI_VERSION < 5)
+ napi_value symbol, external;
+ status = napi_create_symbol(env, nullptr, &symbol);
+ if (status == napi_ok) {
+ status = napi_create_external(env, data, finalizer, hint, &external);
+ if (status == napi_ok) {
+ napi_property_descriptor desc = {nullptr,
+ symbol,
+ nullptr,
+ nullptr,
+ nullptr,
+ external,
+ napi_default,
+ nullptr};
+ status = napi_define_properties(env, obj, 1, &desc);
+ }
+ }
+#else // NAPI_VERSION >= 5
+ status = napi_add_finalizer(env, obj, data, finalizer, hint, nullptr);
+#endif
+ return status;
+}
+
+// For use in JS to C++ callback wrappers to catch any Napi::Error exceptions
+// and rethrow them as JavaScript exceptions before returning from the callback.
+template
+#ifdef NODE_ADDON_API_CPP_EXCEPTIONS_ALL
+inline napi_value WrapCallback(napi_env env, Callable callback) {
+#else
+inline napi_value WrapCallback(napi_env, Callable callback) {
+#endif
+#ifdef NODE_ADDON_API_CPP_EXCEPTIONS
+ try {
+ return callback();
+ } catch (const Error& e) {
+ e.ThrowAsJavaScriptException();
+ return nullptr;
+ }
+#ifdef NODE_ADDON_API_CPP_EXCEPTIONS_ALL
+ catch (const std::exception& e) {
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
+ return nullptr;
+ } catch (...) {
+ Napi::Error::New(env, "A native exception was thrown")
+ .ThrowAsJavaScriptException();
+ return nullptr;
+ }
+#endif // NODE_ADDON_API_CPP_EXCEPTIONS_ALL
+#else // NODE_ADDON_API_CPP_EXCEPTIONS
+ // When C++ exceptions are disabled, errors are immediately thrown as JS
+ // exceptions, so there is no need to catch and rethrow them here.
+ return callback();
+#endif // NODE_ADDON_API_CPP_EXCEPTIONS
+}
+
+// For use in JS to C++ void callback wrappers to catch any Napi::Error
+// exceptions and rethrow them as JavaScript exceptions before returning from
+// the callback.
+template
+inline void WrapVoidCallback(Callable callback) {
+#ifdef NODE_ADDON_API_CPP_EXCEPTIONS
+ try {
+ callback();
+ } catch (const Error& e) {
+ e.ThrowAsJavaScriptException();
+ }
+#else // NAPI_CPP_EXCEPTIONS
+ // When C++ exceptions are disabled, errors are immediately thrown as JS
+ // exceptions, so there is no need to catch and rethrow them here.
+ callback();
+#endif // NAPI_CPP_EXCEPTIONS
+}
+
+// For use in JS to C++ void callback wrappers to catch _any_ thrown exception
+// and rethrow them as JavaScript exceptions before returning from the callback,
+// wrapping in an Napi::Error as needed.
+template
+#ifdef NODE_ADDON_API_CPP_EXCEPTIONS_ALL
+inline void WrapVoidCallback(napi_env env, Callable callback) {
+#else
+inline void WrapVoidCallback(napi_env, Callable callback) {
+#endif
+#ifdef NODE_ADDON_API_CPP_EXCEPTIONS
+ try {
+ callback();
+ } catch (const Error& e) {
+ e.ThrowAsJavaScriptException();
+ }
+#ifdef NODE_ADDON_API_CPP_EXCEPTIONS_ALL
+ catch (const std::exception& e) {
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
+ } catch (...) {
+ Napi::Error::New(env, "A native exception was thrown")
+ .ThrowAsJavaScriptException();
+ }
+#endif // NODE_ADDON_API_CPP_EXCEPTIONS_ALL
+#else
+ // When C++ exceptions are disabled, there is no need to catch and rethrow C++
+ // exceptions. JS errors should be thrown with
+ // `Error::ThrowAsJavaScriptException`.
+ callback();
+#endif // NODE_ADDON_API_CPP_EXCEPTIONS
+}
+
+template
+struct CallbackData {
+ static inline napi_value Wrapper(napi_env env, napi_callback_info info) {
+ return details::WrapCallback(env, [&] {
+ CallbackInfo callbackInfo(env, info);
+ CallbackData* callbackData =
+ static_cast(callbackInfo.Data());
+ callbackInfo.SetData(callbackData->data);
+ return callbackData->callback(callbackInfo);
+ });
+ }
+
+ Callable callback;
+ void* data;
+};
+
+template
+struct CallbackData {
+ static inline napi_value Wrapper(napi_env env, napi_callback_info info) {
+ return details::WrapCallback(env, [&] {
+ CallbackInfo callbackInfo(env, info);
+ CallbackData* callbackData =
+ static_cast(callbackInfo.Data());
+ callbackInfo.SetData(callbackData->data);
+ callbackData->callback(callbackInfo);
+ return nullptr;
+ });
+ }
+
+ Callable callback;
+ void* data;
+};
+
+template
+napi_value TemplatedVoidCallback(napi_env env,
+ napi_callback_info info) NAPI_NOEXCEPT {
+ return details::WrapCallback(env, [&] {
+ CallbackInfo cbInfo(env, info);
+ Callback(cbInfo);
+ return nullptr;
+ });
+}
+
+template
+napi_value TemplatedCallback(napi_env env,
+ napi_callback_info info) NAPI_NOEXCEPT {
+ return details::WrapCallback(env, [&] {
+ CallbackInfo cbInfo(env, info);
+ // MSVC requires to copy 'Callback' function pointer to a local variable
+ // before invoking it.
+ auto callback = Callback;
+ return callback(cbInfo);
+ });
+}
+
+template
+napi_value TemplatedInstanceCallback(napi_env env,
+ napi_callback_info info) NAPI_NOEXCEPT {
+ return details::WrapCallback(env, [&] {
+ CallbackInfo cbInfo(env, info);
+ T* instance = T::Unwrap(cbInfo.This().As