From: Justin Wind Date: Sun, 27 Aug 2023 21:07:04 +0000 (-0700) Subject: Merge branch 'v2.0-dev' as v2.0.0 X-Git-Tag: v2.0.0 X-Git-Url: https://git.squeep.com/?a=commitdiff_plain;h=031c170bdaf1d9c331e6f6fc701ce6540c0e6941;hp=df1c89ca311a06417104e6be0ade6617cbfae60e;p=squeep-api-dingus Merge branch 'v2.0-dev' as v2.0.0 --- diff --git a/CHANGELOG.md b/CHANGELOG.md index ffd23ff..cb60b74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,13 @@ Releases and notable changes to this project are documented here. ## [Unreleased] -- +## [v2.0.0] - 2023-08-27 + +- HEAD requests are now handled automatically by default, if not otherwise specifically registered, on a route with a GET handler +- trailing slashes on a request url now default to being ignored when matching routes +- removed deprecated functions +- minor refactors +- updated devDependencies ## [v1.2.10] - 2023-07-20 @@ -93,7 +99,8 @@ Releases and notable changes to this project are documented here. --- -[Unreleased]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=HEAD;hp=v1.2.10 +[Unreleased]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=HEAD;hp=v2.0.0 +[v2.0.0]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=v2.0.0;hp=v1.2.10 [v1.2.10]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=v1.2.10;hp=v1.2.9 [v1.2.9]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=v1.2.9;hp=v1.2.8 [v1.2.8]: https://git.squeep.com/?p=squeep-api-dingus;a=commitdiff;h=v1.2.8;hp=v1.2.7 diff --git a/README.md b/README.md index 7056184..e4c153c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This is not drop-in compatible with the industry standards, and is in no way int The primary design goals are: - self-contained: Uses as few external dependencies as are feasible. -- not-infinitely-extensible: The projects it gets used in drive the feature set. +- not-infinitely-extensible: The projects it gets used in drive the feature set, so some expected functionality may be surprisingly missing. - learning from mistakes made along the way: This was partly created as a means to gain a better understanding of the existing web framework ecosystem by fussing with all the involved fiddly bits, a priori, from the bottom up. ## Getting Started @@ -16,11 +16,11 @@ The primary design goals are: Construct it with a console-level-compatible logger object capable of doing something meaningful with calls like `logger[level](scopeString, messageString, dataObject)`. Within the server request handler: -- `dispatch(req, res)` makes things go. +- `async dispatch(req, res)` makes things go. Within the application implementation: - `on(method, urlPath, handler)` declares a thing to do when a request matches. -- `preHandler(req, res, ctx)` is called on every request before the handler function, by default adding some request information to the context. +- `async preHandler(req, res, ctx)` is called on every request before the handler function, by default adding some request information to the context. Within your handlers: - parameters from the route and query, along with other metadata, are set in each context. @@ -33,5 +33,9 @@ Negotiated content types can be extended by overriding: - `renderError(contentType, err)` for outgoing types. Some handler functions are provided: -- `handlerGetStaticFile(req, res, ctx, file)` will return a file from a configured directory, and also supports including CERN-style header metadata. It will also serve pre-encoded variations (e.g `.gz` or `.br`) if available and requested. -- `handlerRedirect(req, res, ctx, newPath, statusCode)` will return a redirect response. +- `async handlerGetStaticFile(req, res, ctx, file)` will return a file from a configured directory, and also supports including CERN-style header metadata. It will also serve pre-encoded variations (e.g. `.gz` or `.br`) if available and requested. +- `async handlerRedirect(req, res, ctx, newPath, statusCode)` will return a redirect response. + +## Performance + +While not a specifically-focused target, performance falls roughly midway between [koa](https://koajs.com/) and [fastify](https://fastify.dev/). diff --git a/lib/common.js b/lib/common.js index 723f922..f839e7a 100644 --- a/lib/common.js +++ b/lib/common.js @@ -55,18 +55,6 @@ const generateETag = (_filePath, fileStat, fileData) => { */ const get = (obj, prop, def) => obj && prop && (prop in obj) ? obj[prop] : def; -/** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx - * @deprecated after v1.2.5 (integrated into logger module) - */ -const handlerLogData = (req, res, ctx) => ({ - req: requestLogData(req), - res: responseLogData(res), - ctx, -}); - /** * Determine whether a client has already requested a resource, * based on If-Modified-Since and If-None-Match headers. @@ -171,71 +159,6 @@ const pick = (obj, props) => { return picked; }; -/** - * Return a subset of a request object, suitable for logging. - * Obscures sensitive header values. - * @param {http.ClientRequest} req - * @deprecated after v1.2.5 (integrated into logger module) - */ -const requestLogData = (req) => { - const data = pick(req, [ - 'method', - 'url', - 'httpVersion', - 'headers', - 'trailers', - ]); - scrubHeaderObject(data); - return data; -}; - - -/** - * Remove sensitive header data. - * @param {Object} data - * @param {Object} data.headers - * @deprecated after v1.2.5 (integrated into logger module) - */ -const scrubHeaderObject = (data) => { - if (data?.headers && 'authorization' in data.headers) { - data.headers = Object.assign({}, data.headers, { - authorization: obscureAuthorizationHeader(data.headers['authorization']), - }); - } -}; - - -/** - * Hide sensitive part of an Authorization header. - * @param {String} authHeader - * @returns {String} - * @deprecated after v1.2.5 (integrated into logger module) - */ -const obscureAuthorizationHeader = (authHeader) => { - if (!authHeader) { - return authHeader; - } - const space = authHeader.indexOf(' '); - // This blurs entire string if no space found, because -1. - return authHeader.slice(0, space + 1) + '*'.repeat(authHeader.length - (space + 1)); -}; - - -/** - * Return a subset of a response object, suitable for logging. - * @param {http.ServerResponse} res - * @deprecated after v1.2.5 (integrated into logger module) - */ -const responseLogData = (res) => { - const response = pick(res, [ - 'statusCode', - 'statusMessage', - ]); - response.headers = res.getHeaders(); - return response; -}; - - /** * Store all properties in defaultOptions on target from either options or defaultOptions. * @param {Object} target @@ -269,37 +192,6 @@ const requestId = () => { return uuid.v1(); }; -/** - * Do nothing. - */ -const nop = () => { /**/ }; - -/** - * A logger object which does nothing. - */ -const nullLogger = { - error: nop, - warn: nop, - info: nop, - log: nop, - debug: nop, -}; - -/** - * Populates any absent logger level functions on a logger object. - * @param {Object} logger - * @returns {Object} - * @deprecated after v1.2.9 (this is not our responsibility) - */ -const ensureLoggerLevels = (logger = {}) => { - for (const level in nullLogger) { - if (! (level in logger)) { - logger[level] = nullLogger[level]; - } - } - return logger; -}; - /** * Merges folded header lines * @param {String[]} lines @@ -322,23 +214,15 @@ const unfoldHeaderLines = (lines) => { }; module.exports = { - ensureLoggerLevels, fileScope, generateETag, get, - handlerLogData, httpStatusCodeClass, isClientCached, mergeDeep, mergeEnum, - nop, - nullLogger, - obscureAuthorizationHeader, pick, requestId, - requestLogData, - responseLogData, - scrubHeaderObject, setOptions, splitFirst, unfoldHeaderLines, diff --git a/lib/content-negotiation.js b/lib/content-negotiation.js index 4401374..e78fe35 100644 --- a/lib/content-negotiation.js +++ b/lib/content-negotiation.js @@ -102,6 +102,7 @@ class ContentNegotiation { if (acc === undefined && validTypesQuality[cur] !== 0.0) { return cur; } + // istanbul ignore next // eslint-disable-next-line security/detect-object-injection return validTypesQuality[acc] < validTypesQuality[cur] ? cur : acc; }, undefined); diff --git a/lib/dingus.js b/lib/dingus.js index d8eed91..9bc4282 100644 --- a/lib/dingus.js +++ b/lib/dingus.js @@ -13,7 +13,7 @@ const querystring = require('querystring'); const common = require('./common'); const ContentNegotiation = require('./content-negotiation'); const Enum = require('./enum'); -const { DingusError, ResponseError } = require('./errors'); +const { ResponseError, RouterNoPathError, RouterNoMethodError } = require('./errors'); const { extensionToMime } = require('./mime-helper'); const Router = require('./router'); const Template = require('./template'); @@ -22,13 +22,15 @@ const Template = require('./template'); const _fileScope = common.fileScope(__filename); const defaultOptions = { - ignoreTrailingSlash: false, + ignoreTrailingSlash: true, proxyPrefix: '', strictAccept: true, selfBaseUrl: '', staticMetadata: true, staticPath: undefined, // No reasonable default trustProxy: true, + intrinsicHeadMethod: true, + intrinsicHeadPersistBody: false, querystring, }; @@ -36,15 +38,17 @@ class Dingus { /** * @param {Object} logger object which implements logging methods * @param {Object} options - * @param {Boolean} options.ignoreTrailingSlash + * @param {Boolean} options.ignoreTrailingSlash requests for '/foo/' will match a '/foo' route * @param {string} options.proxyPrefix leading part of url path to strip * @param {Boolean} options.strictAccept whether to error on unsupported Accept type * @param {string} options.selfBaseUrl for constructing links * @param {Boolean} options.staticMetadata serve static headers with static files * @param {Boolean} options.trustProxy trust some header data to be provided by proxy + * @param {Boolean} options.intrinsicHeadMethod handle HEAD requests automatically if not specified as a route method + * @param {Boolean} options.intrinsicHeadPersistBody include un-sent body on ctx for automatic HEAD requests * @param {Object} options.querystring alternate qs parser to use */ - constructor(logger = common.nullLogger, options = {}) { + constructor(logger = console, options = {}) { common.setOptions(this, defaultOptions, options); this.router = new Router(options); @@ -253,13 +257,14 @@ class Dingus { /** - * Dispatch the handler for a request - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {object} ctx + * Resolve the handler to invoke for a request. + * @param {http.ClientRequest} req + * @param {http.ServerResponse} res + * @param {object} ctx + * @returns {object} */ - async dispatch(req, res, ctx = {}) { - const _scope = _fileScope('dispatch'); + _determineHandler(req, res, ctx) { + const _scope = _fileScope('_determineHandler'); const { pathPart, queryParams } = this._splitUrl(req.url); ctx.queryParams = queryParams; @@ -268,26 +273,59 @@ class Dingus { try { ({ handler, handlerArgs } = this.router.lookup(req.method, pathPart, ctx)); } catch (e) { - if (e instanceof DingusError) { - switch (e.message) { - case 'NoPath': - handler = this.handlerNotFound.bind(this); - break; - case 'NoMethod': - handler = this.handlerMethodNotAllowed.bind(this); - break; - default: - this.logger.error(_scope, 'unknown dingus error', { error: e }); - handler = this.handlerInternalServerError.bind(this); - } - } else if (e instanceof URIError) { + if (e instanceof URIError) { handler = this.handlerBadRequest.bind(this); + } else if (e instanceof RouterNoPathError) { + handler = this.handlerNotFound.bind(this); + } else if (e instanceof RouterNoMethodError) { + if (this.intrinsicHeadMethod && req.method === 'HEAD') { + ({ handler, handlerArgs } = this._determineHeadHandler(req, res, ctx, pathPart)); + } else { + handler = this.handlerMethodNotAllowed.bind(this); + } + } else { + this.logger.error(_scope, 'unexpected error', { error: e }); + handler = this.handlerInternalServerError.bind(this); + } + } + return { handler, handlerArgs }; + } + + + /** + * For intrinsic HEAD requests, resolve the handler to invoke. + * @param {http.ClientRequest} req + * @param {http.ServerResponse} res + * @param {object} ctx + * @param {string} pathPart + * @returns {object} + */ + _determineHeadHandler(req, res, ctx, pathPart) { + const _scope = _fileScope('_determineHeadHandler'); + let handler, handlerArgs = []; + try { + ({ handler, handlerArgs } = this.router.lookup('GET', pathPart, ctx)); + Dingus.setHeadHandler(req, res, ctx, this.intrinsicHeadPersistBody); + } catch (e) { + if (e instanceof RouterNoMethodError) { + handler = this.handlerMethodNotAllowed.bind(this); } else { - this.logger.error(_scope, 'lookup failure', { error: e }); + this.logger.error(_scope, 'unexpected error', { error: e }); handler = this.handlerInternalServerError.bind(this); } } + return { handler, handlerArgs }; + } + + /** + * Dispatch the handler for a request + * @param {http.ClientRequest} req + * @param {http.ServerResponse} res + * @param {object} ctx + */ + async dispatch(req, res, ctx = {}) { + const { handler, handlerArgs } = this._determineHandler(req, res, ctx); try { await this.preHandler(req, res, ctx); return await handler(req, res, ctx, ...handlerArgs); @@ -313,16 +351,11 @@ class Dingus { * Parse rawBody as contentType into ctx.parsedBody. * @param {string} contentType * @param {object} ctx - * @param {string|buffer} + * @param {string|buffer} rawBody */ parseBody(contentType, ctx, rawBody) { const _scope = _fileScope('parseBody'); - if (!rawBody) { - // 1.2.4 and earlier expected rawBody on context - rawBody = ctx.rawBody; - } - switch (contentType) { case Enum.ContentType.ApplicationForm: ctx.parsedBody = this.querystring.parse(rawBody); diff --git a/lib/errors.js b/lib/errors.js index ed5b151..942ecc0 100644 --- a/lib/errors.js +++ b/lib/errors.js @@ -22,7 +22,23 @@ class ResponseError extends DingusError { } } +class RouterError extends DingusError { + constructor(...args) { + super(...args); + delete this.stack; + } +} + +class RouterNoPathError extends RouterError { +} + +class RouterNoMethodError extends RouterError { +} + module.exports = { DingusError, ResponseError, + RouterError, + RouterNoPathError, + RouterNoMethodError, }; diff --git a/lib/mime-helper.js b/lib/mime-helper.js index 086dc6a..687d27b 100644 --- a/lib/mime-helper.js +++ b/lib/mime-helper.js @@ -4,15 +4,23 @@ const mimeDb = require('mime-db'); const defaultType = 'application/octet-stream'; + +/** + * Expects mime-db source data as object: + * mime-type: + * source: + * charset: + * compressible: + * extensions: + * Populate `extension` as an index from extensions to mime-types. + */ const extension = {}; for (const [mimeType, entry] of Object.entries(mimeDb)) { - if (entry.extensions) { - entry.extensions.forEach((ext) => { - if (!(ext in extension)) { - extension[ext] = []; - } - extension[ext].push(mimeType); - }); + for (const ext of entry?.extensions || []) { + if (!(ext in extension)) { + extension[ext] = []; + } + extension[ext].push(mimeType); } } @@ -20,8 +28,9 @@ for (const [mimeType, entry] of Object.entries(mimeDb)) { * Return a suitable type for a file extension. * @param {string} ext file extension * @param {string} def type to return if no match + * @returns {string} */ -const extensionToMime = (ext, def = defaultType) => extension[ext] && extension[ext][extension[ext].length - 1] || def; +const extensionToMime = (ext, def = defaultType) => extension?.[ext]?.[0] || def; module.exports = { extensionToMime, diff --git a/lib/router/index.js b/lib/router/index.js index 1585065..fd19bdf 100644 --- a/lib/router/index.js +++ b/lib/router/index.js @@ -7,7 +7,7 @@ const { METHODS: httpMethods } = require('http'); const common = require('../common'); -const { DingusError } = require('../errors'); +const { DingusError, RouterNoPathError, RouterNoMethodError } = require('../errors'); const PathParameter = require('./path-parameter'); // Internal identifiers for route entries. @@ -266,10 +266,10 @@ class Router { if ('*' in matchedPath[kPathMethods]) { return matchedPath[kPathMethods]['*']; } - throw new DingusError('NoMethod'); + throw new RouterNoMethodError(); } ctx.unmatchedPath = pathParts; - throw new DingusError('NoPath'); + throw new RouterNoPathError(); } diff --git a/package-lock.json b/package-lock.json index 848f960..25a4a28 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,22 +1,22 @@ { "name": "@squeep/api-dingus", - "version": "1.2.10", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@squeep/api-dingus", - "version": "1.2.10", + "version": "2.0.0", "license": "ISC", "dependencies": { "mime-db": "^1.52.0", "uuid": "^9.0.0" }, "devDependencies": { - "eslint": "^8.45.0", + "eslint": "^8.48.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-security": "^1.7.1", - "eslint-plugin-sonarjs": "^0.19.0", + "eslint-plugin-sonarjs": "^0.21.0", "mocha": "^10.2.0", "nyc": "^15.1.0", "pre-commit": "^1.2.2", @@ -49,17 +49,89 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.22.9", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", @@ -70,25 +142,25 @@ } }, "node_modules/@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.11.tgz", + "integrity": "sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-compilation-targets": "^7.22.10", "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", + "@babel/helpers": "^7.22.11", + "@babel/parser": "^7.22.11", "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", + "@babel/traverse": "^7.22.11", + "@babel/types": "^7.22.11", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" }, "engines": { @@ -100,12 +172,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", - "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.22.10", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -115,9 +187,9 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", - "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", "dev": true, "dependencies": { "@babel/compat-data": "^7.22.9", @@ -128,9 +200,6 @@ }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-environment-visitor": { @@ -250,27 +319,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.11.tgz", + "integrity": "sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==", "dev": true, "dependencies": { "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.22.11", + "@babel/types": "^7.22.11" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -349,9 +418,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.11.tgz", + "integrity": "sha512-R5zb8eJIBPJriQtbH/htEQy4k7E2dHWlD2Y2VT07JCzwYZHBxV5ZYtM0UhXSNMT74LyxuM+b1jdL7pSesXbC/g==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -375,19 +444,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz", + "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", + "@babel/parser": "^7.22.11", + "@babel/types": "^7.22.11", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -405,9 +474,9 @@ } }, "node_modules/@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz", + "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", @@ -434,18 +503,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", + "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -466,9 +535,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -630,9 +699,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true, "engines": { "node": ">=6.0.0" @@ -654,21 +723,15 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -912,9 +975,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", "dev": true, "funding": [ { @@ -931,9 +994,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", "update-browserslist-db": "^1.0.11" }, "bin": { @@ -983,9 +1046,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001516", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz", - "integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==", + "version": "1.0.30001523", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001523.tgz", + "integrity": "sha512-I5q5cisATTPZ1mc588Z//pj/Ox80ERYDfR71YnvY7raS/NOk8xXlZcB0sF7JdqaV//kOaa6aus7lRfpdnt1eBA==", "dev": true, "funding": [ { @@ -1217,9 +1280,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.462", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.462.tgz", - "integrity": "sha512-ux2LqN9JKRBDKXMT+78jtiBLPiXf+rLtYlsrOg5Qn7uv6Cbg7+9JyIalE3wcqkOdB2wPCUYNWAuL7suKRMHe9w==", + "version": "1.4.502", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.502.tgz", + "integrity": "sha512-xqeGw3Gr6o3uyHy/yKjdnDQHY2RQvXcGC2cfHjccK1IGkH6cX1WQBN8EeC/YpwPhGkBaikDTecJ8+ssxSVRQlw==", "dev": true }, "node_modules/emoji-regex": { @@ -1256,27 +1319,27 @@ } }, "node_modules/eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.48.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -1358,9 +1421,9 @@ } }, "node_modules/eslint-plugin-sonarjs": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.19.0.tgz", - "integrity": "sha512-6+s5oNk5TFtVlbRxqZN7FIGmjdPCYQKaTzFPmqieCmsU1kBYDzndTeQav0xtQNwZJWu5awWfTGe8Srq9xFOGnw==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.21.0.tgz", + "integrity": "sha512-oezUDfFT5S6j3rQheZ4DLPrbetPmMS7zHIKWGHr0CM3g5JgyZroz1FpIKa4jV83NsGpmgIeagpokWDKIJzRQmw==", "dev": true, "engines": { "node": ">=14" @@ -1370,9 +1433,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", - "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -1410,9 +1473,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1645,9 +1708,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -1724,9 +1787,9 @@ } }, "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1883,9 +1946,9 @@ } }, "node_modules/is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -2065,19 +2128,67 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, + "node_modules/istanbul-lib-report/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -2093,9 +2204,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -2995,12 +3106,6 @@ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -3062,12 +3167,12 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "dev": true, "dependencies": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -3136,24 +3241,10 @@ } }, "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "node_modules/safe-regex": { "version": "2.1.1", @@ -3294,12 +3385,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3687,12 +3772,71 @@ } }, "@babel/code-frame": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", - "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", "dev": true, "requires": { - "@babel/highlight": "^7.22.5" + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@babel/compat-data": { @@ -3702,44 +3846,44 @@ "dev": true }, "@babel/core": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", - "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.11.tgz", + "integrity": "sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.9", - "@babel/helper-compilation-targets": "^7.22.9", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-compilation-targets": "^7.22.10", "@babel/helper-module-transforms": "^7.22.9", - "@babel/helpers": "^7.22.6", - "@babel/parser": "^7.22.7", + "@babel/helpers": "^7.22.11", + "@babel/parser": "^7.22.11", "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.8", - "@babel/types": "^7.22.5", + "@babel/traverse": "^7.22.11", + "@babel/types": "^7.22.11", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", + "json5": "^2.2.3", "semver": "^6.3.1" } }, "@babel/generator": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", - "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", "dev": true, "requires": { - "@babel/types": "^7.22.5", + "@babel/types": "^7.22.10", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" } }, "@babel/helper-compilation-targets": { - "version": "7.22.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", - "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", "dev": true, "requires": { "@babel/compat-data": "^7.22.9", @@ -3833,24 +3977,24 @@ "dev": true }, "@babel/helpers": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", - "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.11.tgz", + "integrity": "sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==", "dev": true, "requires": { "@babel/template": "^7.22.5", - "@babel/traverse": "^7.22.6", - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.22.11", + "@babel/types": "^7.22.11" } }, "@babel/highlight": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", - "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.22.5", - "chalk": "^2.0.0", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "dependencies": { @@ -3913,9 +4057,9 @@ } }, "@babel/parser": { - "version": "7.22.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", - "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.11.tgz", + "integrity": "sha512-R5zb8eJIBPJriQtbH/htEQy4k7E2dHWlD2Y2VT07JCzwYZHBxV5ZYtM0UhXSNMT74LyxuM+b1jdL7pSesXbC/g==", "dev": true }, "@babel/template": { @@ -3930,19 +4074,19 @@ } }, "@babel/traverse": { - "version": "7.22.8", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", - "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz", + "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.22.5", - "@babel/generator": "^7.22.7", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", "@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-function-name": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.7", - "@babel/types": "^7.22.5", + "@babel/parser": "^7.22.11", + "@babel/types": "^7.22.11", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -3956,9 +4100,9 @@ } }, "@babel/types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", - "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz", + "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.22.5", @@ -3976,15 +4120,15 @@ } }, "@eslint-community/regexpp": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", - "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", + "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", "dev": true }, "@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -3999,9 +4143,9 @@ } }, "@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", "dev": true }, "@humanwhocodes/config-array": { @@ -4122,9 +4266,9 @@ } }, "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", "dev": true }, "@jridgewell/set-array": { @@ -4140,21 +4284,13 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - } + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "@nodelib/fs.scandir": { @@ -4354,14 +4490,14 @@ "dev": true }, "browserslist": { - "version": "4.21.9", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", - "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001503", - "electron-to-chromium": "^1.4.431", - "node-releases": "^2.0.12", + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", "update-browserslist-db": "^1.0.11" } }, @@ -4396,9 +4532,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001516", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz", - "integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==", + "version": "1.0.30001523", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001523.tgz", + "integrity": "sha512-I5q5cisATTPZ1mc588Z//pj/Ox80ERYDfR71YnvY7raS/NOk8xXlZcB0sF7JdqaV//kOaa6aus7lRfpdnt1eBA==", "dev": true }, "chalk": { @@ -4563,9 +4699,9 @@ } }, "electron-to-chromium": { - "version": "1.4.462", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.462.tgz", - "integrity": "sha512-ux2LqN9JKRBDKXMT+78jtiBLPiXf+rLtYlsrOg5Qn7uv6Cbg7+9JyIalE3wcqkOdB2wPCUYNWAuL7suKRMHe9w==", + "version": "1.4.502", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.502.tgz", + "integrity": "sha512-xqeGw3Gr6o3uyHy/yKjdnDQHY2RQvXcGC2cfHjccK1IGkH6cX1WQBN8EeC/YpwPhGkBaikDTecJ8+ssxSVRQlw==", "dev": true }, "emoji-regex": { @@ -4593,27 +4729,27 @@ "dev": true }, "eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.48.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -4671,16 +4807,16 @@ } }, "eslint-plugin-sonarjs": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.19.0.tgz", - "integrity": "sha512-6+s5oNk5TFtVlbRxqZN7FIGmjdPCYQKaTzFPmqieCmsU1kBYDzndTeQav0xtQNwZJWu5awWfTGe8Srq9xFOGnw==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.21.0.tgz", + "integrity": "sha512-oezUDfFT5S6j3rQheZ4DLPrbetPmMS7zHIKWGHr0CM3g5JgyZroz1FpIKa4jV83NsGpmgIeagpokWDKIJzRQmw==", "dev": true, "requires": {} }, "eslint-scope": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", - "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -4705,9 +4841,9 @@ } }, "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, "espree": { @@ -4868,9 +5004,9 @@ "dev": true }, "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "optional": true }, @@ -4922,9 +5058,9 @@ } }, "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -5041,9 +5177,9 @@ } }, "is-core-module": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", - "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "dev": true, "requires": { "has": "^1.0.3" @@ -5174,14 +5310,49 @@ } }, "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", "dev": true, "requires": { "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", + "make-dir": "^4.0.0", "supports-color": "^7.1.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } } }, "istanbul-lib-source-maps": { @@ -5196,9 +5367,9 @@ } }, "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -5901,12 +6072,6 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true } } }, @@ -5953,12 +6118,12 @@ "dev": true }, "resolve": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", - "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "dev": true, "requires": { - "is-core-module": "^2.11.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -5994,9 +6159,9 @@ } }, "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "safe-regex": { @@ -6115,14 +6280,6 @@ "dev": true, "requires": { "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } } }, "string-width": { diff --git a/package.json b/package.json index 5ae6e87..4e2fbe5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@squeep/api-dingus", - "version": "1.2.10", + "version": "2.0.0", "description": "An API server framework", "main": "index.js", "scripts": { @@ -26,10 +26,10 @@ "uuid": "^9.0.0" }, "devDependencies": { - "eslint": "^8.45.0", + "eslint": "^8.48.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-security": "^1.7.1", - "eslint-plugin-sonarjs": "^0.19.0", + "eslint-plugin-sonarjs": "^0.21.0", "mocha": "^10.2.0", "nyc": "^15.1.0", "pre-commit": "^1.2.2", diff --git a/test/lib/common.js b/test/lib/common.js index 57c4113..15e9c4a 100644 --- a/test/lib/common.js +++ b/test/lib/common.js @@ -128,100 +128,6 @@ describe('common', function () { }); }); // pick - describe('requestLogData', function () { - it('gives data', function () { - const req = { - method: 'GET', - somethingElse: 'blah', - }; - const result = common.requestLogData(req); - assert.deepStrictEqual(result, { - method: 'GET', - }); - }); - }); // requestLogData - - describe('obscureAuthorizationHeader', function () { - it('obscures basic data', function () { - const authHeader = 'Basic Zm9vOmJhcg=='; - const expected = 'Basic ************'; - const result = common.obscureAuthorizationHeader(authHeader); - assert.strictEqual(result, expected); - }); - it('obscures all of other types', function () { - const authHeader = 'someWeirdAuth'; - const expected = '*************'; - const result = common.obscureAuthorizationHeader(authHeader); - assert.strictEqual(result, expected); - }); - it('does nothing when empty', function () { - const authHeader = undefined; - const expected = undefined; - const result = common.obscureAuthorizationHeader(authHeader); - assert.strictEqual(result, expected); - }); - }); // obscureAuthorizationHeader - - describe('scrubHeaderObject', function () { - it('', function () { - const data = { - headers: { - 'foo': 'bar', - 'authorization': 'Basic Zm9vOmJhcg==', - }, - }; - const expected = { - headers: { - 'foo': 'bar', - 'authorization': 'Basic ************', - }, - }; - common.scrubHeaderObject(data); - assert.deepStrictEqual(data, expected); - }); - }); // scrubHeaderObject - - describe('responseLogData', function () { - it('gives data', function () { - const res = { - getHeaders: () => ({}), - statusCode: 200, - blah: 'blah', - }; - const result = common.responseLogData(res); - assert.deepStrictEqual(result, { - headers: {}, - statusCode: 200, - }); - }); - }); // responseLogData - - describe('handlerLogData', function () { - it('covers', function () { - const req = { - method: 'GET', - somethingElse: 'blah', - }; - const res = { - getHeaders: () => ({}), - statusCode: 200, - blah: 'blah', - }; - const ctx = {}; - const result = common.handlerLogData(req, res, ctx); - assert.deepStrictEqual(result, { - req: { - method: 'GET', - }, - res: { - headers: {}, - statusCode: 200, - }, - ctx: {}, - }); - }); - }); // handlerLogData - describe('setOptions', function () { it('sets options', function () { const expected = { @@ -324,13 +230,6 @@ describe('common', function () { }); }); // requestId - describe('ensureLoggerLevels', function () { - it('adds missing levels', function () { - const result = common.ensureLoggerLevels(); - assert.deepStrictEqual(result, common.nullLogger); - }); - }); // ensureLoggerLevels - describe('httpStatusCodeClass', function () { it('works', function () { for (const [statusCode, statusClassExpected] of Object.entries({ diff --git a/test/lib/dingus.js b/test/lib/dingus.js index 12f40e8..9d47122 100644 --- a/test/lib/dingus.js +++ b/test/lib/dingus.js @@ -7,15 +7,20 @@ const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-requi const fs = require('fs'); const Dingus = require('../../lib/dingus'); -const { DingusError } = require('../../lib/errors'); +const { DingusError, RouterNoMethodError } = require('../../lib/errors'); const Enum = require('../../lib/enum'); const noExpectedException = 'did not get expected exception'; +const noLogger = { + debug: () => {}, + error: () => {}, +}; + describe('Dingus', function () { let dingus; beforeEach(function () { - dingus = new Dingus(); + dingus = new Dingus(noLogger, {}); }); afterEach(function () { sinon.restore(); @@ -23,7 +28,7 @@ describe('Dingus', function () { describe('constructor', function () { it('covers', function () { - const d = new Dingus({}, {}); + const d = new Dingus(); assert(d); }); }); // constructor @@ -36,7 +41,7 @@ describe('Dingus', function () { }); it('returns normal path', function () { const p = '////a///b/./bar/..///c'; - const expected = '/a/b/c' + const expected = '/a/b/c'; const r = dingus._normalizePath(p); assert.strictEqual(r, expected); }); @@ -152,7 +157,7 @@ describe('Dingus', function () { const expected = { clientAddress: '', clientProtocol: 'http', - } + }; dingus.clientAddressContext(req, res, ctx); assert.deepStrictEqual(ctx, expected); assert(!req.getHeader.called); @@ -162,7 +167,7 @@ describe('Dingus', function () { const expected = { clientAddress: '::1', clientProtocol: 'https', - } + }; req.connection.remoteAddress = '::1'; req.connection.encrypted = true; dingus.clientAddressContext(req, res, ctx); @@ -350,6 +355,7 @@ describe('Dingus', function () { sinon.spy(dingus, 'handlerNotFound'); sinon.spy(dingus, 'handlerBadRequest'); sinon.spy(dingus, 'handlerInternalServerError'); + sinon.spy(Dingus, 'setHeadHandler'); stubHandler = sinon.stub(); }); afterEach(function () { @@ -455,6 +461,40 @@ describe('Dingus', function () { assert.strictEqual(stubHandler.args[0][3], 'foo'); assert.strictEqual(stubHandler.args[0][4], 'bar'); }); + describe('intrinsic HEAD handling', function () { + it('covers no intrinsic HEAD handling', async function () { + dingus.intrinsicHeadMethod = false; + dingus.on('GET', '/', stubHandler); + req.method = 'HEAD'; + await dingus.dispatch(req, res, ctx); + assert(!stubHandler.called); + assert(dingus.handlerMethodNotAllowed.called); + }); + it('calls HEAD setup and GET handler', async function () { + dingus.on('GET', '/', stubHandler); + req.method = 'HEAD'; + await dingus.dispatch(req, res, ctx); + assert(Dingus.setHeadHandler.called); + assert(stubHandler.called); + }); + it('covers no GET handler', async function () { + dingus.on('POST', '/', stubHandler); + req.method = 'HEAD'; + await dingus.dispatch(req, res, ctx); + assert(!stubHandler.called); + assert(dingus.handlerMethodNotAllowed.called); + }); + it('covers unexpected router error', async function () { + sinon.stub(dingus.router, 'lookup') + .onFirstCall().throws(new RouterNoMethodError()) + .onSecondCall().throws(new DingusError()) + ; + dingus.on('GET', '/', stubHandler); + req.method = 'HEAD'; + await dingus.dispatch(req, res, ctx); + assert(dingus.handlerInternalServerError.called); + }); + }); }); // dispatch describe('parseBody', function () { @@ -472,14 +512,14 @@ describe('Dingus', function () { }); it('parses json', function () { const src = { foo: 'bar' }; - ctx.rawBody = JSON.stringify(src); - dingus.parseBody(Enum.ContentType.ApplicationJson, ctx); + const rawBody = JSON.stringify(src); + dingus.parseBody(Enum.ContentType.ApplicationJson, ctx, rawBody); assert.deepStrictEqual(ctx.parsedBody, src); }); it('handles unparsable json', function () { - ctx.rawBody = 'not json'; + const rawBody = 'not json'; try { - dingus.parseBody(Enum.ContentType.ApplicationJson, ctx); + dingus.parseBody(Enum.ContentType.ApplicationJson, ctx, rawBody); assert.fail(noExpectedException); } catch (e) { assert.strictEqual(e.statusCode, 400); @@ -489,8 +529,8 @@ describe('Dingus', function () { const expected = Object.assign(Object.create(null), { foo: 'bar', }); - ctx.rawBody = 'foo=bar'; - dingus.parseBody('application/x-www-form-urlencoded', ctx); + const rawBody = 'foo=bar'; + dingus.parseBody('application/x-www-form-urlencoded', ctx, rawBody); assert.deepStrictEqual(ctx.parsedBody, expected); }); @@ -549,7 +589,7 @@ describe('Dingus', function () { const req = {}; const res = {}; const ctx = {}; - sinon.stub(dingus, 'bodyData').resolves('{"foo":"bar"}') + sinon.stub(dingus, 'bodyData').resolves('{"foo":"bar"}'); sinon.stub(Dingus, 'getRequestContentType').returns(Enum.ContentType.ApplicationJson); await dingus.ingestBody(req, res, ctx); assert.deepStrictEqual(ctx.parsedBody, { foo: 'bar' }); diff --git a/test/lib/enum.js b/test/lib/enum.js index 0a86ec5..bdd353f 100644 --- a/test/lib/enum.js +++ b/test/lib/enum.js @@ -9,13 +9,18 @@ const Enum = require('../../lib/enum'); describe('enum', function () { describe('ErrorResponse', function () { - it('covers default', function () { + it('covers broken', function () { const result = Enum.ErrorResponse.notPresent; const expected = { errorMessage: 'undefined error response \'notPresent\'', }; assert.deepStrictEqual(result, expected); }); + it('covers success', function () { + const { statusCode } = Enum.ErrorResponse.ReallyForbidden; + const expected = 403; + assert.deepStrictEqual(statusCode, expected); + }); }); // ErrorResponse }); diff --git a/test/lib/router.js b/test/lib/router.js index c89cc19..bcb45f2 100644 --- a/test/lib/router.js +++ b/test/lib/router.js @@ -5,8 +5,8 @@ const assert = require('assert'); const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require const Router = require('../../lib/router'); -const PathParameter = require('../../lib/router/path-parameter') -const { DingusError } = require('../../lib/errors'); +const PathParameter = require('../../lib/router/path-parameter'); +const { DingusError, RouterNoPathError, RouterNoMethodError } = require('../../lib/errors'); const noExpectedException = 'did not get expected exception'; @@ -311,8 +311,7 @@ describe('Router', function () { router.lookup(method, path, ctx); assert.fail(noExpectedException); } catch (e) { - assert(e instanceof DingusError); - assert.strictEqual(e.message, 'NoPath'); + assert(e instanceof RouterNoPathError); } }); it('finds handler', function () { @@ -353,8 +352,7 @@ describe('Router', function () { router.lookup(method, path, ctx); assert.fail(noExpectedException); } catch (e) { - assert(e instanceof DingusError); - assert.strictEqual(e.message, 'NoMethod'); + assert(e instanceof RouterNoMethodError); } }); it('does not lookup non-existent path', async function () { @@ -365,8 +363,7 @@ describe('Router', function () { router.lookup(method, path, ctx); assert.fail(noExpectedException); } catch (e) { - assert(e instanceof DingusError); - assert.strictEqual(e.message, 'NoPath'); + assert(e instanceof RouterNoPathError); } });