From: Justin Wind Date: Sat, 22 Jun 2024 20:35:26 +0000 (-0700) Subject: Merge branch 'v1.3-dev' X-Git-Tag: v1.3.12 X-Git-Url: https://git.squeep.com/?a=commitdiff_plain;h=8cd88ab4087a7fab2ccd6e231c64d7f0f1299f26;hp=429d914b206ac0e8b8dc8bbb1afad022b8dcf1a2;p=websub-hub Merge branch 'v1.3-dev' --- diff --git a/.eslintrc.json b/.eslintrc.json index 10477c0..5ab981d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,7 +12,7 @@ "plugin:sonarjs/recommended" ], "parserOptions": { - "ecmaVersion": 2018 + "ecmaVersion": "latest" }, "plugins": [ "node", diff --git a/CHANGELOG.md b/CHANGELOG.md index fa40422..df4ad40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ Releases and notable changes to this project are documented here. +## [v1.3.12] - 2024-06-22 + +### Added + +- Account credential management interface. + +### Fixed + +- Dependency updates. + ## [v1.3.11] - 2023-03-22 ### Fixed diff --git a/config/default.js b/config/default.js index 3f54d9a..58ba307 100644 --- a/config/default.js +++ b/config/default.js @@ -5,6 +5,10 @@ const { name: packageName, version: packageVersion } = require('../package.json'); const common = require('../src/common'); const Enum = require('../src/enum'); +const roman = require('@squeep/roman'); + +const currentYear = (new Date()).getFullYear(); +const romanYearHTML = roman.toRoman(currentYear, true); const defaultOptions = { // Uniquely identify this instance, used to tag work-in-progress. @@ -51,7 +55,7 @@ const defaultOptions = { logoUrl: 'static/logo.svg', // image to go with title footerEntries: [ // common footers on all html pages 'Development Repository / GitHub mirror', - '©', + `©`, ], publishHistoryDays: 60, // Number of days of update history to show on topic details page strictSecrets: false, // If true, reject requests with secrets but not over https @@ -60,6 +64,7 @@ const defaultOptions = { }, communication: { + requestTimeoutMs: 120000, strictTopicHubLink: true, // If true, deletes topics which do not list us (dingus.selfBaseUrl) as a hub relation. retryBackoffSeconds: [60, 120, 360, 1440, 7200, 43200, 86400], // failed requests retry according to number of attempts claimTimeoutSeconds: 600, // how long until an in-progress task is deemed abandoned diff --git a/config/index.js b/config/index.js index d06162e..8f31211 100644 --- a/config/index.js +++ b/config/index.js @@ -5,6 +5,11 @@ const common = require('../src/common'); const defaultEnvironment = 'development'; const testEnvironment = 'test'; +/** + * Merge environment-specific config objects on top of defaults. + * @param {string=} environment from NODE_ENV + * @returns {object} config + */ function Config(environment) { environment = environment || defaultEnvironment; const defaultConfig = require('./default'); diff --git a/documentation/media/postgres-er.svg b/documentation/media/postgres-er.svg index 8610593..26a00ff 100644 --- a/documentation/media/postgres-er.svg +++ b/documentation/media/postgres-er.svg @@ -1,7 +1,7 @@ - Websub Hub Entity-Relations Postgres -Schema 1.0.4 +Schema 1.1.0 topic @@ -238,17 +238,19 @@ authentication - - -AUTHENTICATION + + +AUTHENTICATION + +created -created +last_authenticated -last_authenticated +identifier -identifier +credential -credential +otp_key diff --git a/documentation/media/sqlite-er.svg b/documentation/media/sqlite-er.svg index 91752cb..0d151f4 100644 --- a/documentation/media/sqlite-er.svg +++ b/documentation/media/sqlite-er.svg @@ -1,7 +1,7 @@ - Websub Hub Entity-Relations SQLite -Schema 1.0.4 +Schema 1.1.0 topic @@ -238,17 +238,19 @@ authentication - - -AUTHENTICATION + + +AUTHENTICATION + +created -created +last_authenticated -last_authenticated +identifier -identifier +credential -credential +otp_key diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..fcda56f --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,7 @@ +'use strict'; + +const squeepConfig = require('@squeep/eslint-config'); + +module.exports = [ + ...squeepConfig, +]; diff --git a/package-lock.json b/package-lock.json index a1f93a1..4fdc394 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,100 +1,99 @@ { "name": "@squeep/websub-hub", - "version": "1.3.11", - "lockfileVersion": 2, + "version": "1.3.12", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@squeep/websub-hub", - "version": "1.3.11", + "version": "1.3.12", "license": "ISC", "dependencies": { - "@squeep/api-dingus": "git+https://git.squeep.com/squeep-api-dingus/#v1.2.9", - "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.3.0", - "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.4.0", - "@squeep/logger-json-console": "git+https://git.squeep.com/squeep-logger-json-console#v1.0.2", - "@squeep/web-linking": "^1.0.7", - "axios": "^1.3.4", - "feedparser": "^2.2.10", - "htmlparser2": "^8.0.2", - "iconv": "^3.0.1" + "@squeep/api-dingus": "^2", + "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.5.0", + "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.6.1", + "@squeep/logger-json-console": "^3", + "@squeep/roman": "^1", + "@squeep/web-linking": "^1", + "feedparser": "^2", + "got": "^14", + "htmlparser2": "^9", + "iconv": "^3" }, "devDependencies": { - "eslint": "^8.36.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-security": "^1.7.1", - "eslint-plugin-sonarjs": "^0.19.0", - "html-minifier-lint": "^2.0.0", - "mocha": "^10.2.0", - "mocha-steps": "^1.3.0", - "nyc": "^15.1.0", - "pre-commit": "^1.2.2", - "sinon": "^15.0.2" + "@squeep/eslint-config": "^1", + "eslint": "^9", + "html-validate": "^8", + "mocha": "^10", + "mocha-steps": "^1", + "nyc": "^17", + "pre-commit": "^1", + "sinon": "^18" }, "engines": { - "node": ">=14" + "node": ">=20" }, "optionalDependencies": { - "better-sqlite3": "^8.2.0", - "pg-promise": "^11.4.3" + "better-sqlite3": "^11", + "pg-promise": "^11" } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", - "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.3", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.3", - "@babel/types": "^7.21.3", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -104,211 +103,205 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dev": true, "dependencies": { - "@babel/types": "^7.21.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", "dev": true, + "dependencies": { + "@babel/types": "^7.24.7" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, "dependencies": { - "@babel/types": "^7.20.2" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/helper-validator-identifier": "^7.24.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -386,9 +379,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -398,34 +391,34 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", - "debug": "^4.1.0", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -442,23 +435,40 @@ } }, "node_modules/@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz", + "integrity": "sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==", + "dev": true, + "dependencies": { + "@types/eslint": "^8.56.5", + "@types/estree": "^1.0.5", + "@typescript-eslint/types": "^7.2.0", + "comment-parser": "1.4.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", - "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, "dependencies": { "eslint-visitor-keys": "^3.3.0" @@ -470,25 +480,51 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "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" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.16.0.tgz", + "integrity": "sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -496,33 +532,52 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", + "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@html-validate/stylish": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@html-validate/stylish/-/stylish-4.2.0.tgz", + "integrity": "sha512-Nl8HCv0hGRSLQ+n1OD4Hk3a+Urwk9HH0vQkAzzCarT4KlA7bRl+6xEiS5PZVwOmjtC7XiH/oNe3as9Fxcr2A1w==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "kleur": "^4.0.0" }, "engines": { - "node": ">=10.10.0" + "node": ">= 16" } }, "node_modules/@humanwhocodes/module-importer": { @@ -538,11 +593,62 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -659,67 +765,68 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "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.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "engines": { "node": ">=6.0.0" } }, "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==", + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "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/@mapbox/node-pre-gyp": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", - "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", + "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", "optional": true, "dependencies": { - "detect-libc": "^2.0.0", + "detect-libc": "^1.0.3", "https-proxy-agent": "^5.0.0", "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", + "node-fetch": "^2.6.1", "nopt": "^5.0.0", - "npmlog": "^5.0.1", + "npmlog": "^4.1.2", "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" + "semver": "^7.3.4", + "tar": "^6.1.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" @@ -769,37 +876,70 @@ "node": ">=10" } }, - "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, - "dependencies": { - "type-detect": "4.0.8" + "optional": true, + "engines": { + "node": ">=14" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==" + }, + "node_modules/@sidvind/better-ajv-errors": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@sidvind/better-ajv-errors/-/better-ajv-errors-2.1.3.tgz", + "integrity": "sha512-lWuod/rh7Xz5uXiEGSfm2Sd5PG7K/6yJfoAZVqzsEswjPJhUz15R7Gn/o8RczA041QS15hBd/BCSeu9vwPArkA==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0" + "@babel/code-frame": "^7.16.0", + "chalk": "^4.1.0" + }, + "engines": { + "node": ">= 16.14" + }, + "peerDependencies": { + "ajv": "4.11.8 - 8" } }, - "node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "node_modules/@sindresorhus/is": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-6.3.1.tgz", + "integrity": "sha512-FX4MfcifwJyFOI2lPoX7PQxCqx8BG1HCho7WdiXwpEQx1Ycij0JxkfYtGK7yqNScrZGSlt6RE6sw8QYoH7eKnQ==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, + "node_modules/@sinonjs/fake-timers": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, "node_modules/@sinonjs/samsam": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-7.0.1.tgz", - "integrity": "sha512-zsAk2Jkiq89mhZovB2LLOdTCxJF4hqqTToGP0ASWlhp4I1hqOjcfmZGafXntCN7MDC6yySH0mFHrYtHceOeLmw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", + "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", "dev": true, "dependencies": { "@sinonjs/commons": "^2.0.0", @@ -823,102 +963,191 @@ "dev": true }, "node_modules/@squeep/api-dingus": { - "version": "1.2.9", - "resolved": "git+https://git.squeep.com/squeep-api-dingus/#3b15b5ff792fc5d61be8337989058c297460cd99", - "license": "ISC", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@squeep/api-dingus/-/api-dingus-2.1.2.tgz", + "integrity": "sha512-d4jj0TL0qDz/ADWMqwPkmJ/eFy2fhzFTP2iBTcAzIG/ZH0y0Xtic8XdZct5kiihAVQC6ut3SCptkxXKeA7K/mA==", "dependencies": { + "@squeep/log-helper": "^1", "mime-db": "^1.52.0", - "uuid": "^9.0.0" + "uuid": "^9.0.1" }, "engines": { - "node": ">=14" + "node": ">=14.13.1" } }, "node_modules/@squeep/authentication-module": { - "version": "1.3.0", - "resolved": "git+https://git.squeep.com/squeep-authentication-module/#6557437fcef1d780b54e39ab93e07a6be36e4447", - "license": "ISC", + "version": "1.5.0", + "resolved": "git+https://git.squeep.com/squeep-authentication-module/#5ea2ffe571a74618eef073c58c5fef06e1cf06a7", "dependencies": { - "@squeep/api-dingus": "git+https://git.squeep.com/squeep-api-dingus/#v1.2.9", - "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.4.0", - "@squeep/indieauth-helper": "git+https://git.squeep.com/squeep-indieauth-helper/#v1.2.0", - "@squeep/mystery-box": "^2.0.1" + "@squeep/api-dingus": "^2", + "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.6.1", + "@squeep/indieauth-helper": "^1", + "@squeep/mystery-box": "^2", + "@squeep/totp": "^1", + "uuid": "^9" }, "engines": { - "node": ">=14" + "node": ">=18" }, "optionalDependencies": { - "argon2": "^0.30.3", + "argon2": "^0.40.1", "node-linux-pam": "^0.2.1" } }, - "node_modules/@squeep/base64url": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@squeep/base64url/-/base64url-1.0.5.tgz", - "integrity": "sha512-J1UBXYQ4tBuHGnFfg0MdmxCP3oEti7jJWK/qBsg520d8tZd10sL6TXiMDGdBiH9GD3OtlfSYf6wWIN4QfdW21A==", + "node_modules/@squeep/eslint-config": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@squeep/eslint-config/-/eslint-config-1.0.1.tgz", + "integrity": "sha512-LID0nJW/+Sk+7AKWM9gVEwk5O8NXvlo1+TApOOlZ4RZDaRqkH1EnEqxZcX/MKjuyRh8D5XEU0fn72MsiEjeEiA==", + "dev": true, + "dependencies": { + "@eslint/js": "^9", + "eslint-plugin-jsdoc": "^48", + "eslint-plugin-n": "^17", + "eslint-plugin-security": "^3", + "eslint-plugin-sonarjs": "^1", + "globals": "^15" + }, "engines": { - "node": ">=14" + "node": ">=20" + }, + "peerDependencies": { + "eslint": ">= 9" } }, "node_modules/@squeep/html-template-helper": { - "version": "1.4.0", - "resolved": "git+https://git.squeep.com/squeep-html-template-helper#100046316a87631fb8814f80b35647709e6c7319", - "license": "ISC", + "version": "1.6.1", + "resolved": "git+https://git.squeep.com/squeep-html-template-helper#93d1b030d6b3c6ea93c36a46f4940181a1acaca0", "dependencies": { - "@squeep/lazy-property": "^1.1.2" + "@squeep/lazy-property": "^1" }, "engines": { - "node": ">=14" + "node": ">=14.13.1" } }, "node_modules/@squeep/indieauth-helper": { - "version": "1.2.0", - "resolved": "git+https://git.squeep.com/squeep-indieauth-helper/#732e70f9f59315443a9127ecc5df68f1059cf14d", - "license": "ISC", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@squeep/indieauth-helper/-/indieauth-helper-1.4.2.tgz", + "integrity": "sha512-PKOr2Mx8e1RwdJ6ab22gWAlbzktDNORIt4xzGZ0iXbvbTdqNLdpAKBHi8Il0vYgZU0HAO3utNqMX5grSfKaDrw==", "dependencies": { - "@squeep/base64url": "^1.0.5", - "@squeep/web-linking": "^1.0.7", - "axios": "^1.1.3", - "iconv": "^3.0.1", - "ip-address": "^8.1.0", - "microformats-parser": "^1.4.1" + "@squeep/log-helper": "^1", + "@squeep/web-linking": "^1", + "got": "^14", + "iconv": "^3", + "ip-address": "^9", + "microformats-parser": "^2" }, "engines": { - "node": ">=14" + "node": ">=20" } }, "node_modules/@squeep/lazy-property": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@squeep/lazy-property/-/lazy-property-1.1.2.tgz", - "integrity": "sha512-wRdR4IOqWXoDMArx0HPo5MtM2Wk5wemAULbZ6PabVw1ylSQekkzKfoAUuupxsKuzjcRPjZvbpGDv+i04hBMnQw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@squeep/lazy-property/-/lazy-property-1.1.3.tgz", + "integrity": "sha512-GzQ/bSE6MZ6YeRjLMKK18I0ajvOnhrgacZs6EpLERXPPlQZWkOcmjCcjyqY71lqd5MzsPbSwzsj6Uonpqea6nw==", "engines": { "node": ">=14" } }, + "node_modules/@squeep/log-helper": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@squeep/log-helper/-/log-helper-1.0.1.tgz", + "integrity": "sha512-T+QTxSNoZ9wzyyK1jS8ac9puOikRv14MfkE3uXSBOp70T8eEqCjSwfE+VHtOb0riU4FhYpDsBNSMIskK4UDRZA==", + "engines": { + "node": ">=14.13.1" + } + }, "node_modules/@squeep/logger-json-console": { - "version": "1.0.2", - "resolved": "git+https://git.squeep.com/squeep-logger-json-console#dbff0fa5f018f7a302f73250e55f761c0ccf24b1", - "license": "ISC", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@squeep/logger-json-console/-/logger-json-console-3.0.3.tgz", + "integrity": "sha512-W8BDrV0fHKABbFXOedJKd8hmIgKOtTCM0lLGmaGsDfV8+OAdEg4kdS0F8GI7PLF9mOzp/z0uRv+CCyv5tS81kA==", "engines": { - "node": ">=12.0.0" + "node": ">=17" } }, "node_modules/@squeep/mystery-box": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@squeep/mystery-box/-/mystery-box-2.0.1.tgz", - "integrity": "sha512-is8Uqvcm27pm49ZaQL/KOizo89SiTuTZElQoyuPX34TvcnsOTN2eN2YxdVSwKusZwYi+mmE8brrAtBcM/Ttpwg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@squeep/mystery-box/-/mystery-box-2.0.3.tgz", + "integrity": "sha512-OFPVVyYrxZU/8iwJGBRpyh+z9AyEqryWyh8p45LtaHw62hwOb8k2J8An4jFmYU0fiMRR+b3xR94qt0/V+ansyA==", "engines": { "node": "^14 >=14.18.0 || >=15.7.0" } }, + "node_modules/@squeep/roman": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@squeep/roman/-/roman-1.0.2.tgz", + "integrity": "sha512-VFNjvSTR96r1Ii7zTxweUimiyoxs9cRo6TXXwjR/dX+riOL+YERvhf2w5M+mYYC3QhKP+j9aUVFrTWgjJV3MIw==" + }, + "node_modules/@squeep/totp": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@squeep/totp/-/totp-1.1.5.tgz", + "integrity": "sha512-keqggH2NrHs8hqzyov31zIA4XTLUxwXBn+VfUFlCdzZY2omoWbgm4742Ht8j3W48FLtIX1q4Zrm1ncObi9RfMA==", + "dependencies": { + "base32.js": "^0.1.0", + "qrcode-svg": "^1.1.0" + }, + "engines": { + "node": ">14" + } + }, "node_modules/@squeep/web-linking": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@squeep/web-linking/-/web-linking-1.0.7.tgz", - "integrity": "sha512-9d3QijrWc/WNE7p/K7NLUHbmPf92CURRqfzDLV0cGqYNA4QWAPfzwC8hxWpdUkUnep3KakvLKK60l0kEBMM3ag==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@squeep/web-linking/-/web-linking-1.0.9.tgz", + "integrity": "sha512-NHI2sWiL7PduRBYhM54MqG40xnI867uRyjKDWBCudsel4DmLy3Jh1CIvYORbPt8ScvvL0PV7kCsmowPdufAOkA==", "engines": { "node": ">=14.0" } }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@typescript-eslint/types": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", + "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -926,9 +1155,9 @@ "optional": true }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1062,46 +1291,39 @@ "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=14" } }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "deprecated": "This package is no longer supported.", "optional": true, "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, "node_modules/argon2": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.30.3.tgz", - "integrity": "sha512-DoH/kv8c9127ueJSBxAVJXinW9+EuPA3EMUxoV2sAY1qDE5H9BjTyVF/aD2XyHqbqUWabgBkIfcP3ZZuGhbJdg==", + "version": "0.40.3", + "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.40.3.tgz", + "integrity": "sha512-FrSmz4VeM91jwFvvjsQv9GYp6o/kARWoYKjbjDB2U5io1H3e5X67PYGclFDeQff6UXIhUd4aHR3mxCdBbMMuQw==", "hasInstallScript": true, "optional": true, "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.10", "@phc/format": "^1.0.0", - "node-addon-api": "^5.0.0" + "node-addon-api": "^8.0.0", + "node-gyp-build": "^4.8.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.17.0" } }, "node_modules/argparse": { @@ -1124,27 +1346,20 @@ "node": ">=10.0.0" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", - "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", - "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "devOptional": true }, + "node_modules/base32.js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", + "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1166,23 +1381,26 @@ "optional": true }, "node_modules/better-sqlite3": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.2.0.tgz", - "integrity": "sha512-8eTzxGk9535SB3oSNu0tQ6I4ZffjVCBUjKHN9QeeIFtphBX0sEd0NxAuglBNR9TO5ThnxBB7GqzfcYo9kjadJQ==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.0.0.tgz", + "integrity": "sha512-1NnNhmT3EZTsKtofJlMox1jkMxdedILury74PwUbQBjWgo4tL4kf7uTAjU55mgQwjdzqakSTjkf+E1imrFwjnA==", "hasInstallScript": true, "optional": true, "dependencies": { "bindings": "^1.5.0", - "prebuild-install": "^7.1.0" + "prebuild-install": "^7.1.1" } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bindings": { @@ -1230,12 +1448,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -1248,9 +1466,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "dev": true, "funding": [ { @@ -1260,13 +1478,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" - } + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -1305,13 +1527,55 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "optional": true, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", "engines": { - "node": ">=4" + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-12.0.1.tgz", + "integrity": "sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==", + "dependencies": { + "@types/http-cache-semantics": "^4.0.4", + "get-stream": "^9.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.4", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.1", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/caching-transform": { @@ -1338,16 +1602,6 @@ "node": ">=6" } }, - "node_modules/camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1358,9 +1612,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001469", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", - "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==", + "version": "1.0.30001636", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz", + "integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==", "dev": true, "funding": [ { @@ -1370,6 +1624,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -1437,18 +1695,6 @@ "node": ">=10" } }, - "node_modules/clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", - "dev": true, - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 4.0" - } - }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -1469,6 +1715,43 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -1496,32 +1779,15 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "devOptional": true }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "optional": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, "engines": { - "node": ">= 0.8" + "node": ">= 12.0.0" } }, - "node_modules/commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -1581,9 +1847,9 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", "devOptional": true, "dependencies": { "ms": "2.1.2" @@ -1610,7 +1876,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "optional": true, "dependencies": { "mimic-response": "^3.1.0" }, @@ -1621,6 +1886,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -1636,6 +1912,15 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/default-require-extensions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", @@ -1651,12 +1936,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "engines": { - "node": ">=0.4.0" + "node": ">=10" } }, "node_modules/delegates": { @@ -1666,12 +1951,15 @@ "optional": true }, "node_modules/detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, "engines": { - "node": ">=8" + "node": ">=0.10" } }, "node_modules/diff": { @@ -1683,18 +1971,6 @@ "node": ">=0.3.1" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -1734,29 +2010,35 @@ } }, "node_modules/domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" + "domhandler": "^5.0.3" }, "funding": { "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/electron-to-chromium": { - "version": "1.4.336", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.336.tgz", - "integrity": "sha512-yLaoSY/ngjgRpEGU4ueeW0vlj456idQBn74r6s1yutoOIadvd7rwt05TGenPj0PoetJ5pEHomVkmfTdIgqPfJw==", + "version": "1.4.807", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.807.tgz", + "integrity": "sha512-kSmJl2ZwhNf/bcIuCH/imtNOKlpkLDn2jqT5FJ+/0CXjhnFaOa9cOe9gHKKy71eM49izwuQjZhKk+lWQ1JxB7A==", "dev": true }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "devOptional": true + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true }, "node_modules/end-of-stream": { "version": "1.4.4", @@ -1767,10 +2049,23 @@ "once": "^1.4.0" } }, + "node_modules/enhanced-resolve": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", + "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "engines": { "node": ">=0.12" }, @@ -1785,9 +2080,9 @@ "dev": true }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, "engines": { "node": ">=6" @@ -1806,201 +2101,230 @@ } }, "node_modules/eslint": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", - "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.5.0.tgz", + "integrity": "sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.1", - "@eslint/js": "8.36.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/config-array": "^0.16.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.5.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@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.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.5.0", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.0.1", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" } }, - "node_modules/eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", "dev": true, "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" + "semver": "^7.5.4" }, "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "node": ">=12" }, "peerDependencies": { - "eslint": ">=4.19.1" + "eslint": ">=6.0.0" } }, - "node_modules/eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "node_modules/eslint-plugin-es-x": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.7.0.tgz", + "integrity": "sha512-aP3qj8BwiEDPttxQkZdI221DLKq9sI/qHolE2YSQL1/9+xk7dTV+tB1Fz8/IaCA+lnLA1bDEnvaS2LKs0k2Uig==", "dev": true, + "funding": [ + "https://github.com/sponsors/ota-meshi", + "https://opencollective.com/eslint" + ], "dependencies": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.6.0", + "eslint-compat-utils": "^0.5.1" }, "engines": { - "node": ">=8.10.0" + "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "eslint": ">=5.16.0" + "eslint": ">=8" } }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/eslint-plugin-jsdoc": { + "version": "48.2.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.12.tgz", + "integrity": "sha512-sO9sKkJx5ovWoRk9hV0YiNzXQ4Z6j27CqE/po2E3wddZVuy9wvKPSTiIhpxMTrP/qURvKayJIDB2+o9kyCW1Fw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "@es-joy/jsdoccomment": "~0.43.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "semver": "^7.6.2", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, - "node_modules/eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "node_modules/eslint-plugin-n": { + "version": "17.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.9.0.tgz", + "integrity": "sha512-CPSaXDXdrT4nsrOrO4mT4VB6FMUkoySRkHWuuJJHVqsIEjIeZgMY1H7AzSwPbDScikBmLN82KeM1u7ixV7PzGg==", "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "enhanced-resolve": "^5.17.0", + "eslint-plugin-es-x": "^7.5.0", + "get-tsconfig": "^4.7.0", + "globals": "^15.0.0", + "ignore": "^5.2.4", + "minimatch": "^9.0.0", + "semver": "^7.5.3" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": ">=8.23.0" } }, - "node_modules/eslint-plugin-security": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", - "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", + "node_modules/eslint-plugin-n/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "safe-regex": "^2.1.1" + "balanced-match": "^1.0.0" } }, - "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==", + "node_modules/eslint-plugin-n/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=14" + "node": ">=16 || 14 >=14.17" }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "node_modules/eslint-plugin-security": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-3.0.1.tgz", + "integrity": "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q==", "dev": true, "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "safe-regex": "^2.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "node_modules/eslint-plugin-sonarjs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-1.0.3.tgz", + "integrity": "sha512-6s41HLPYPyDrp+5+7Db5yFYbod6h9pC7yx+xfcNwHRcLe1EZwbbQT/tdOAkR7ekVUkNGEvN3GmYakIoQUX7dEg==", "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, "engines": { - "node": ">=6" + "node": ">=16" }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "peerDependencies": { + "eslint": "^8.0.0 || ^9.0.0" } }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "node_modules/eslint-scope": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", + "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/espree": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", - "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2089,9 +2413,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -2120,15 +2444,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-uri-to-path": { @@ -2138,9 +2462,9 @@ "optional": true }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -2192,67 +2516,46 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dev": true, "dependencies": { "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, + "node_modules/form-data-encoder": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-4.0.2.tgz", + "integrity": "sha512-KQVhvhK8ZkWzxKxOr56CPulAhH3dobtuQ4+hNQ+HekH/Wp5gSOafqRAeTphQUJAIk0GBvHZgJ2ZGRWd5kphMuw==", "engines": { - "node": ">= 6" + "node": ">= 18" } }, "node_modules/fromentries": { @@ -2318,9 +2621,9 @@ "devOptional": 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, @@ -2331,30 +2634,74 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "deprecated": "This package is no longer supported.", "optional": true, "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", + "aproba": "^1.0.3", "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "optional": true, + "dependencies": { + "number-is-nan": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true + }, + "node_modules/gauge/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "optional": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "optional": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, "node_modules/gensync": { @@ -2384,6 +2731,29 @@ "node": ">=8.0.0" } }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", + "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -2391,20 +2761,23 @@ "optional": true }, "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "devOptional": true, + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz", + "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==", + "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2422,45 +2795,73 @@ "node": ">=10.13.0" } }, - "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.6.0.tgz", + "integrity": "sha512-UzcJi88Hw//CurUIRa9Jxb0vgOCcuD/MNjwmXp633cyaRKkCWACkoqHCtfZv43b1kqXGg/fpOa8bwgacCeXsVg==", + "dev": true, + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/got": { + "version": "14.4.1", + "resolved": "https://registry.npmjs.org/got/-/got-14.4.1.tgz", + "integrity": "sha512-IvDJbJBUeexX74xNQuMIVgCRRuNOm5wuK+OC3Dc2pnSoh1AOmgc7JVj7WC+cJ4u0aPcO9KZ2frTXcqK4W/5qTQ==", + "dependencies": { + "@sindresorhus/is": "^6.3.1", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^12.0.1", + "decompress-response": "^6.0.0", + "form-data-encoder": "^4.0.2", + "get-stream": "^8.0.1", + "http2-wrapper": "^2.2.1", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^4.0.1", + "responselike": "^3.0.0", + "type-fest": "^4.19.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2516,46 +2917,87 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "node_modules/html-validate": { + "version": "8.20.1", + "resolved": "https://registry.npmjs.org/html-validate/-/html-validate-8.20.1.tgz", + "integrity": "sha512-EawDiHzvZtnbBIfxE90lvKOWqNsmZGqRXTy+utxlGo525Vqjowg+RK42q1AeJ6zm1AyVTFIDSah1eBe9tc6YHg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/html-validate" + } + ], + "workspaces": [ + "docs", + "tests/vitest" + ], "dependencies": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" + "@babel/code-frame": "^7.10.0", + "@html-validate/stylish": "^4.1.0", + "@sidvind/better-ajv-errors": "2.1.3", + "ajv": "^8.0.0", + "deepmerge": "4.3.1", + "glob": "^10.0.0", + "ignore": "5.3.1", + "kleur": "^4.1.0", + "minimist": "^1.2.0", + "prompts": "^2.0.0", + "semver": "^7.0.0" }, "bin": { - "html-minifier": "cli.js" + "html-validate": "bin/html-validate.js" }, "engines": { - "node": ">=4" + "node": ">= 16.14" + }, + "peerDependencies": { + "jest": "^27.1 || ^28.1.3 || ^29.0.3", + "jest-diff": "^27.1 || ^28.1.3 || ^29.0.3", + "jest-snapshot": "^27.1 || ^28.1.3 || ^29.0.3", + "vitest": "^0.34 || ^1" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + }, + "jest-diff": { + "optional": true + }, + "jest-snapshot": { + "optional": true + }, + "vitest": { + "optional": true + } } }, - "node_modules/html-minifier-lint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-minifier-lint/-/html-minifier-lint-2.0.0.tgz", - "integrity": "sha512-halWZUg/us7Y16irVM90DTdyAUP3ksFthWfFPJTG1jpBaYYyGHt9azTW9H++hZ8LWRArzQm9oIcrfM/o/CO+4A==", + "node_modules/html-validate/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dev": true, "dependencies": { - "html-minifier": "3.x" - }, - "bin": { - "html-minifier-lint": "cli.js" + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/html-validate/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -2566,8 +3008,25 @@ "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" + "domutils": "^3.1.0", + "entities": "^4.5.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" } }, "node_modules/https-proxy-agent": { @@ -2613,9 +3072,9 @@ "optional": true }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -2659,6 +3118,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "devOptional": true, "dependencies": { "once": "^1.3.0", @@ -2677,12 +3137,12 @@ "optional": true }, "node_modules/ip-address": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-8.1.0.tgz", - "integrity": "sha512-Wz91gZKpNKoXtqvY8ScarKYwhXoK4r/b5QuT+uywe/azv0/nUCo7Bh0IRRI7F9DHR06kJNWtzMGLIbXavngbKA==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "dependencies": { "jsbn": "1.1.0", - "sprintf-js": "1.1.2" + "sprintf-js": "^1.1.3" }, "engines": { "node": ">= 12" @@ -2700,18 +3160,6 @@ "node": ">=8" } }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2820,9 +3268,9 @@ "dev": true }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" @@ -2841,27 +3289,19 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", "dev": true, "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node": ">=10" } }, "node_modules/istanbul-lib-processinfo": { @@ -2891,17 +3331,32 @@ } }, "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/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-source-maps": { @@ -2919,9 +3374,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.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -2931,14 +3386,22 @@ "node": ">=8" } }, - "node_modules/js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", + "node_modules/jackspeak": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/js-tokens": { @@ -2964,6 +3427,15 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -2976,6 +3448,11 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3001,11 +3478,28 @@ } }, "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", "dev": true }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3082,11 +3576,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", - "dev": true + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/lru-cache": { "version": "5.1.1", @@ -3113,23 +3612,23 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "devOptional": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/microformats-parser": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/microformats-parser/-/microformats-parser-1.4.1.tgz", - "integrity": "sha512-BSg9Y/Aik8hvvme/fkxnXMRvTKuVwOeTapeZdaPQ+92DEubyM31iMtwbgFZ1383om643UvfYY5G23E9s1FY2KQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/microformats-parser/-/microformats-parser-2.0.2.tgz", + "integrity": "sha512-tUf9DmN4Jq/tGyp1YH2V6D/Cud+9Uc0WhjjUFirqVeHTRkkfLDacv6BQFT7h7HFsD0Z8wja5eKkRgzZU8bv0Fw==", "dependencies": { - "parse5": "^6.0.0" + "parse5": "^7.1.2" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/mime-db": { @@ -3140,27 +3639,15 @@ "node": ">= 0.6" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimatch": { @@ -3179,18 +3666,18 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "optional": true, + "devOptional": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", - "optional": true, + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minizlib": { @@ -3243,9 +3730,9 @@ "optional": true }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", + "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", "dev": true, "dependencies": { "ansi-colors": "4.1.1", @@ -3255,13 +3742,12 @@ "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.2.0", + "glob": "8.1.0", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "5.0.1", "ms": "2.1.3", - "nanoid": "3.3.3", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", @@ -3276,10 +3762,6 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" } }, "node_modules/mocha-steps": { @@ -3297,6 +3779,49 @@ "balanced-match": "^1.0.0" } }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/mocha/node_modules/minimatch": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", @@ -3344,18 +3869,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "devOptional": true }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", @@ -3369,40 +3882,22 @@ "dev": true }, "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.0.0.tgz", + "integrity": "sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==", "dev": true, "dependencies": { - "lower-case": "^1.1.1" + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" } }, "node_modules/node-abi": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.33.0.tgz", - "integrity": "sha512-7GGVawqyHF4pfd0YFybhv/eM9JwTtPqx0mAanQ146O3FlSh3pA24zf9IRQTOsfTSqXTNzPSP5iagAJ94jjuVog==", + "version": "3.65.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz", + "integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==", "optional": true, "dependencies": { "semver": "^7.3.5" @@ -3412,15 +3907,18 @@ } }, "node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "optional": true + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.0.0.tgz", + "integrity": "sha512-ipO7rsHEBqa9STO5C5T10fj732ml+5kLN1cAG8/jdHd56ldQeGj3Q7+scUS+VHK/qy1zLEwC4wMK5+yM0btPvw==", + "optional": true, + "engines": { + "node": "^18 || ^20 || >= 21" + } }, "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "optional": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -3437,6 +3935,17 @@ } } }, + "node_modules/node-gyp-build": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", + "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, "node_modules/node-linux-pam": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-linux-pam/-/node-linux-pam-0.2.1.tgz", @@ -3457,45 +3966,6 @@ "node": ">=8.6.0" } }, - "node_modules/node-linux-pam/node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", - "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", - "optional": true, - "dependencies": { - "detect-libc": "^1.0.3", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.1", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "rimraf": "^3.0.2", - "semver": "^7.3.4", - "tar": "^6.1.0" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/node-linux-pam/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-linux-pam/node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "optional": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, "node_modules/node-linux-pam/node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -3507,38 +3977,11 @@ "wrap-ansi": "^6.2.0" } }, - "node_modules/node-linux-pam/node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-linux-pam/node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "optional": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-linux-pam/node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } + "node_modules/node-linux-pam/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "optional": true }, "node_modules/node-linux-pam/node_modules/find-up": { "version": "4.1.0", @@ -3553,48 +3996,6 @@ "node": ">=8" } }, - "node_modules/node-linux-pam/node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", - "optional": true, - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/node-linux-pam/node_modules/gauge/node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "optional": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-linux-pam/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "optional": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/node-linux-pam/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -3613,18 +4014,6 @@ "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==", "optional": true }, - "node_modules/node-linux-pam/node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "optional": true, - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, "node_modules/node-linux-pam/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -3652,16 +4041,18 @@ "node": ">=8" } }, - "node_modules/node-linux-pam/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "node_modules/node-linux-pam/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "optional": true, "dependencies": { - "ansi-regex": "^2.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/node-linux-pam/node_modules/wrap-ansi": { @@ -3678,27 +4069,6 @@ "node": ">=8" } }, - "node_modules/node-linux-pam/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-linux-pam/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "optional": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/node-linux-pam/node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -3753,9 +4123,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/nopt": { @@ -3782,16 +4152,28 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "deprecated": "This package is no longer supported.", "optional": true, "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, "node_modules/number-is-nan": { @@ -3804,9 +4186,9 @@ } }, "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-17.0.0.tgz", + "integrity": "sha512-ISp44nqNCaPugLLGGfknzQwSwt10SSS5IMoPR7GLoMAyS18Iw5js8U7ga2VF9lYuMZ42gOHr3UddZw4WZltxKg==", "dev": true, "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", @@ -3821,7 +4203,7 @@ "glob": "^7.1.6", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^6.0.2", "istanbul-lib-processinfo": "^2.0.2", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", @@ -3841,7 +4223,7 @@ "nyc": "bin/nyc.js" }, "engines": { - "node": ">=8.9" + "node": ">=18" } }, "node_modules/nyc/node_modules/cliui": { @@ -3855,6 +4237,12 @@ "wrap-ansi": "^6.2.0" } }, + "node_modules/nyc/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/nyc/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -3868,11 +4256,45 @@ "node": ">=8" } }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, + "node_modules/nyc/node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/nyc/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nyc/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -3916,6 +4338,26 @@ "node": ">=8" } }, + "node_modules/nyc/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/nyc/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/nyc/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -3990,9 +4432,9 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { "deep-is": "^0.1.3", @@ -4000,7 +4442,7 @@ "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -4015,6 +4457,14 @@ "node": ">= 0.4.0" } }, + "node_modules/p-cancelable": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-4.0.1.tgz", + "integrity": "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==", + "engines": { + "node": ">=14.16" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -4081,20 +4531,11 @@ "node": ">=8" } }, - "node_modules/packet-reader": { + "node_modules/package-json-from-dist": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", - "optional": true - }, - "node_modules/param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", - "dev": true, - "dependencies": { - "no-case": "^2.2.0" - } + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true }, "node_modules/parent-module": { "version": "1.0.1", @@ -4109,9 +4550,15 @@ } }, "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } }, "node_modules/path-exists": { "version": "4.0.0", @@ -4140,44 +4587,55 @@ "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "isarray": "0.0.1" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-to-regexp/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-to-regexp": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", + "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", "dev": true }, "node_modules/pg": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.10.0.tgz", - "integrity": "sha512-ke7o7qSTMb47iwzOSaZMfeR7xToFdkE71ifIipOAAaLIM0DYzfOAXlgFFmYUIE2BcJtvnVlGCID84ZzCegE8CQ==", + "version": "8.11.5", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.5.tgz", + "integrity": "sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==", "optional": true, "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.5.0", - "pg-pool": "^3.6.0", - "pg-protocol": "^1.6.0", + "pg-connection-string": "^2.6.4", + "pg-pool": "^3.6.2", + "pg-protocol": "^1.6.1", "pg-types": "^2.1.0", "pgpass": "1.x" }, "engines": { "node": ">= 8.0.0" }, + "optionalDependencies": { + "pg-cloudflare": "^1.1.1" + }, "peerDependencies": { "pg-native": ">=3.0.1" }, @@ -4187,10 +4645,16 @@ } } }, + "node_modules/pg-cloudflare": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", + "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "optional": true + }, "node_modules/pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.4.tgz", + "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==", "optional": true }, "node_modules/pg-int8": { @@ -4203,32 +4667,32 @@ } }, "node_modules/pg-minify": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.3.tgz", - "integrity": "sha512-NoSsPqXxbkD8RIe+peQCqiea4QzXgosdTKY8p7PsbbGsh2F8TifDj/vJxfuR8qJwNYrijdSs7uf0tAe6WOyCsQ==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.4.tgz", + "integrity": "sha512-cf6hBt1YqzqPX0OznXKSv4U7e4o7eUU4zp2zQsbJ+4OCNNr7EnnAVWkIz4k0dv6UN4ouS1ZL4WlXxCrZHHl69g==", "optional": true, "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" } }, "node_modules/pg-pool": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz", - "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.2.tgz", + "integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==", "optional": true, "peerDependencies": { "pg": ">=8.0" } }, "node_modules/pg-promise": { - "version": "11.4.3", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.4.3.tgz", - "integrity": "sha512-b4wuukB+pkrLRZ53Z+3L9IONlIhOUSM/VlLQV2SnQzNJPJmDZj6ticgcMtZMDanAUEj+zX1FJOBrSpSR9TumXg==", + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.8.0.tgz", + "integrity": "sha512-w9hTFpkM4FByJTJ7KCWLtZSOtQa2BKC+XIV8+3ZvDlfYfBYdz8V4V+BttnqhUPY/d12Itug7Bft4XdILihsY+w==", "optional": true, "dependencies": { "assert-options": "0.8.1", - "pg": "8.10.0", - "pg-minify": "1.6.3", + "pg": "8.11.5", + "pg-minify": "1.6.4", "spex": "3.3.0" }, "engines": { @@ -4236,9 +4700,9 @@ } }, "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.1.tgz", + "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==", "optional": true }, "node_modules/pg-types": { @@ -4267,9 +4731,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "node_modules/picomatch": { @@ -4460,9 +4924,9 @@ "dev": true }, "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "optional": true, "dependencies": { "detect-libc": "^2.0.0", @@ -4485,6 +4949,15 @@ "node": ">=10" } }, + "node_modules/prebuild-install/node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4511,10 +4984,27 @@ "node": ">=8" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } }, "node_modules/pseudomap": { "version": "1.0.2", @@ -4533,14 +5023,22 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" } }, + "node_modules/qrcode-svg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/qrcode-svg/-/qrcode-svg-1.1.0.tgz", + "integrity": "sha512-XyQCIXux1zEIA3NPb0AeR8UMYvXZzWEhgdBgBjH9gO7M48H9uoHzviNz8pXw3UzrAcxRRRn9gxHewAVK7bn9qw==", + "bin": { + "qrcode-svg": "bin/qrcode-svg.js" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4561,6 +5059,17 @@ } ] }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -4621,35 +5130,14 @@ } }, "node_modules/regexp-tree": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", - "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", "dev": true, "bin": { "regexp-tree": "bin/regexp-tree" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -4671,28 +5159,25 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "devOptional": true }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "node_modules/resolve-from": { "version": "4.0.0", @@ -4703,6 +5188,29 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4717,6 +5225,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "devOptional": true, "dependencies": { "glob": "^7.1.3" @@ -4728,6 +5237,27 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "devOptional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -4766,18 +5296,15 @@ } }, "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "optional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "devOptional": true, "bin": { "semver": "bin/semver.js" }, @@ -4785,24 +5312,6 @@ "node": ">=10" } }, - "node_modules/semver/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==", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", @@ -4840,10 +5349,16 @@ } }, "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "devOptional": true + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/simple-concat": { "version": "1.0.1", @@ -4891,17 +5406,17 @@ } }, "node_modules/sinon": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.0.2.tgz", - "integrity": "sha512-PCVP63XZkg0/LOqQH5rEU4LILuvTFMb5tNxTHfs6VUMNnZz2XrnGSTZbAGITjzwQWbl/Bl/8hi4G3zZWjyBwHg==", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-18.0.0.tgz", + "integrity": "sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==", "dev": true, "dependencies": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/samsam": "^7.0.1", - "diff": "^5.1.0", - "nise": "^5.1.4", - "supports-color": "^7.2.0" + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/samsam": "^8.0.0", + "diff": "^5.2.0", + "nise": "^6.0.0", + "supports-color": "^7" }, "funding": { "type": "opencollective", @@ -4909,14 +5424,20 @@ } }, "node_modules/sinon/node_modules/diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "engines": { "node": ">=0.3.1" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4954,6 +5475,47 @@ "node": ">=8" } }, + "node_modules/spawn-wrap/node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/spawn-wrap/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "dev": true + }, "node_modules/spex": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/spex/-/spex-3.3.0.tgz", @@ -4964,18 +5526,18 @@ } }, "node_modules/split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "optional": true, "engines": { "node": ">= 10.x" } }, "node_modules/sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" }, "node_modules/string_decoder": { "version": "1.1.1", @@ -4992,11 +5554,29 @@ "optional": true }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, - "dependencies": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" @@ -5005,6 +5585,39 @@ "node": ">=8" } }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -5017,6 +5630,19 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -5050,27 +5676,24 @@ "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, "node_modules/tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "optional": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" @@ -5127,6 +5750,15 @@ "node": ">= 6" } }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/tar/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -5147,6 +5779,27 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5214,12 +5867,11 @@ } }, "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, + "version": "4.20.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.20.1.tgz", + "integrity": "sha512-R6wDsVsoS9xYOpy8vgeBlqpdOyzJ12HNfQhC/aAKWM3YoCV9TtunJzh/QpkMgeDhkoynDcw5f1y+qF9yc/HHyg==", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5240,32 +5892,10 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/uglify-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", - "dev": true, - "dependencies": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uglify-js/node_modules/commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "dev": true, "funding": [ { @@ -5275,25 +5905,23 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" } }, - "node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", - "dev": true - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -5309,9 +5937,13 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } @@ -5348,9 +5980,9 @@ } }, "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "devOptional": true }, "node_modules/wide-align": { @@ -5362,10 +5994,30 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, + "node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "optional": true + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -5378,6 +6030,24 @@ "dev": true }, "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", @@ -5394,6 +6064,65 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -5412,6 +6141,12 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -5502,6 +6237,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -5514,4141 +6269,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", - "dev": true - }, - "@babel/core": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", - "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.3", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.3", - "@babel/types": "^7.21.3", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", - "dev": true, - "requires": { - "@babel/types": "^7.21.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true - }, - "@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", - "dev": true, - "requires": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" - } - }, - "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dev": true, - "requires": { - "@babel/types": "^7.20.2" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", - "dev": true - }, - "@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", - "dev": true, - "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "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/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", - "dev": true - }, - "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - } - }, - "@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - } - }, - "@eslint-community/eslint-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", - "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", - "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - } - }, - "@eslint/js": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", - "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@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==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@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/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@mapbox/node-pre-gyp": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", - "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", - "optional": true, - "requires": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@phc/format": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", - "integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==", - "optional": true - }, - "@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^2.0.0" - }, - "dependencies": { - "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - } - } - }, - "@sinonjs/samsam": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-7.0.1.tgz", - "integrity": "sha512-zsAk2Jkiq89mhZovB2LLOdTCxJF4hqqTToGP0ASWlhp4I1hqOjcfmZGafXntCN7MDC6yySH0mFHrYtHceOeLmw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^2.0.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - }, - "dependencies": { - "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - } - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", - "dev": true - }, - "@squeep/api-dingus": { - "version": "git+https://git.squeep.com/squeep-api-dingus/#3b15b5ff792fc5d61be8337989058c297460cd99", - "from": "@squeep/api-dingus@git+https://git.squeep.com/squeep-api-dingus/#v1.2.9", - "requires": { - "mime-db": "^1.52.0", - "uuid": "^9.0.0" - } - }, - "@squeep/authentication-module": { - "version": "git+https://git.squeep.com/squeep-authentication-module/#6557437fcef1d780b54e39ab93e07a6be36e4447", - "from": "@squeep/authentication-module@git+https://git.squeep.com/squeep-authentication-module/#v1.3.0", - "requires": { - "@squeep/api-dingus": "git+https://git.squeep.com/squeep-api-dingus/#v1.2.9", - "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.4.0", - "@squeep/indieauth-helper": "git+https://git.squeep.com/squeep-indieauth-helper/#v1.2.0", - "@squeep/mystery-box": "^2.0.1", - "argon2": "^0.30.3", - "node-linux-pam": "^0.2.1" - } - }, - "@squeep/base64url": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@squeep/base64url/-/base64url-1.0.5.tgz", - "integrity": "sha512-J1UBXYQ4tBuHGnFfg0MdmxCP3oEti7jJWK/qBsg520d8tZd10sL6TXiMDGdBiH9GD3OtlfSYf6wWIN4QfdW21A==" - }, - "@squeep/html-template-helper": { - "version": "git+https://git.squeep.com/squeep-html-template-helper#100046316a87631fb8814f80b35647709e6c7319", - "from": "@squeep/html-template-helper@git+https://git.squeep.com/squeep-html-template-helper#v1.4.0", - "requires": { - "@squeep/lazy-property": "^1.1.2" - } - }, - "@squeep/indieauth-helper": { - "version": "git+https://git.squeep.com/squeep-indieauth-helper/#732e70f9f59315443a9127ecc5df68f1059cf14d", - "from": "@squeep/indieauth-helper@git+https://git.squeep.com/squeep-indieauth-helper/#v1.2.0", - "requires": { - "@squeep/base64url": "^1.0.5", - "@squeep/web-linking": "^1.0.7", - "axios": "^1.1.3", - "iconv": "^3.0.1", - "ip-address": "^8.1.0", - "microformats-parser": "^1.4.1" - } - }, - "@squeep/lazy-property": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@squeep/lazy-property/-/lazy-property-1.1.2.tgz", - "integrity": "sha512-wRdR4IOqWXoDMArx0HPo5MtM2Wk5wemAULbZ6PabVw1ylSQekkzKfoAUuupxsKuzjcRPjZvbpGDv+i04hBMnQw==" - }, - "@squeep/logger-json-console": { - "version": "git+https://git.squeep.com/squeep-logger-json-console#dbff0fa5f018f7a302f73250e55f761c0ccf24b1", - "from": "@squeep/logger-json-console@git+https://git.squeep.com/squeep-logger-json-console#v1.0.2" - }, - "@squeep/mystery-box": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@squeep/mystery-box/-/mystery-box-2.0.1.tgz", - "integrity": "sha512-is8Uqvcm27pm49ZaQL/KOizo89SiTuTZElQoyuPX34TvcnsOTN2eN2YxdVSwKusZwYi+mmE8brrAtBcM/Ttpwg==" - }, - "@squeep/web-linking": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@squeep/web-linking/-/web-linking-1.0.7.tgz", - "integrity": "sha512-9d3QijrWc/WNE7p/K7NLUHbmPf92CURRqfzDLV0cGqYNA4QWAPfzwC8hxWpdUkUnep3KakvLKK60l0kEBMM3ag==" - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "optional": true - }, - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "addressparser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-1.0.1.tgz", - "integrity": "sha512-aQX7AISOMM7HFE0iZ3+YnD07oIeJqWGVnJ+ZIKaBZAk03ftmVYVqsGas/rbXKR21n4D/hKCSHypvcyOkds/xzg==" - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "optional": true, - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "devOptional": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "devOptional": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "requires": { - "default-require-extensions": "^3.0.0" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "optional": true - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "optional": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "argon2": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.30.3.tgz", - "integrity": "sha512-DoH/kv8c9127ueJSBxAVJXinW9+EuPA3EMUxoV2sAY1qDE5H9BjTyVF/aD2XyHqbqUWabgBkIfcP3ZZuGhbJdg==", - "optional": true, - "requires": { - "@mapbox/node-pre-gyp": "^1.0.10", - "@phc/format": "^1.0.0", - "node-addon-api": "^5.0.0" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-indexofobject": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-indexofobject/-/array-indexofobject-0.0.1.tgz", - "integrity": "sha512-tpdPBIBm4TMNxSp8O3pZgC7mF4+wn9SmJlhE+7bi5so6x39PvzUqChQMbv93R5ilYGZ1HV+Neki4IH/i+87AoQ==" - }, - "assert-options": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.1.tgz", - "integrity": "sha512-5lNGRB5g5i2bGIzb+J1QQE1iKU/WEMVBReFIc5pPDWjcPj23otPL0eI6PB2v7QPi0qU6Mhym5D3y0ZiSIOf3GA==", - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "axios": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", - "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", - "requires": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "devOptional": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "optional": true - }, - "better-sqlite3": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-8.2.0.tgz", - "integrity": "sha512-8eTzxGk9535SB3oSNu0tQ6I4ZffjVCBUjKHN9QeeIFtphBX0sEd0NxAuglBNR9TO5ThnxBB7GqzfcYo9kjadJQ==", - "optional": true, - "requires": { - "bindings": "^1.5.0", - "prebuild-install": "^7.1.0" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "optional": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "optional": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "devOptional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "optional": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "optional": true - }, - "caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "requires": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==", - "dev": true, - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "devOptional": true - }, - "caniuse-lite": { - "version": "1.0.30001469", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", - "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "optional": true - }, - "clean-css": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", - "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", - "optional": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "devOptional": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "devOptional": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "optional": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "devOptional": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "optional": true - }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "devOptional": true, - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "devOptional": true - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "optional": true, - "requires": { - "mimic-response": "^3.1.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "optional": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "default-require-extensions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", - "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", - "dev": true, - "requires": { - "strip-bom": "^4.0.0" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "optional": true - }, - "detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", - "optional": true - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" - }, - "domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "requires": { - "domelementtype": "^2.3.0" - } - }, - "domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", - "requires": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" - } - }, - "electron-to-chromium": { - "version": "1.4.336", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.336.tgz", - "integrity": "sha512-yLaoSY/ngjgRpEGU4ueeW0vlj456idQBn74r6s1yutoOIadvd7rwt05TGenPj0PoetJ5pEHomVkmfTdIgqPfJw==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "devOptional": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "optional": true, - "requires": { - "once": "^1.4.0" - } - }, - "entities": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", - "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==" - }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", - "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.1", - "@eslint/js": "8.36.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "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.1.1", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.5.0", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - } - }, - "eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "dev": true, - "requires": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - } - }, - "eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", - "dev": true, - "requires": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "dev": true, - "requires": {} - }, - "eslint-plugin-security": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", - "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", - "dev": true, - "requires": { - "safe-regex": "^2.1.1" - } - }, - "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==", - "dev": true, - "requires": {} - }, - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", - "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", - "dev": true, - "requires": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "optional": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "feedparser": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/feedparser/-/feedparser-2.2.10.tgz", - "integrity": "sha512-WoAOooa61V8/xuKMi2pEtK86qQ3ZH/M72EEGdqlOTxxb3m6ve1NPvZcmPFs3wEDfcBbFLId2GqZ4YjsYi+h1xA==", - "requires": { - "addressparser": "^1.0.1", - "array-indexofobject": "~0.0.1", - "lodash.assign": "^4.2.0", - "lodash.get": "^4.4.2", - "lodash.has": "^4.5.2", - "lodash.uniq": "^4.5.0", - "mri": "^1.1.5", - "readable-stream": "^2.3.7", - "sax": "^1.2.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" - }, - "foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "optional": true - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "optional": true, - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "optional": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "devOptional": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "optional": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "devOptional": true - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", - "optional": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "devOptional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "optional": true - }, - "hasha": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", - "dev": true, - "requires": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", - "dev": true, - "requires": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" - } - }, - "html-minifier-lint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-minifier-lint/-/html-minifier-lint-2.0.0.tgz", - "integrity": "sha512-halWZUg/us7Y16irVM90DTdyAUP3ksFthWfFPJTG1jpBaYYyGHt9azTW9H++hZ8LWRArzQm9oIcrfM/o/CO+4A==", - "dev": true, - "requires": { - "html-minifier": "3.x" - } - }, - "htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "requires": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "optional": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "iconv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/iconv/-/iconv-3.0.1.tgz", - "integrity": "sha512-lJnFLxVc0d82R7GfU7a9RujKVUQ3Eee19tPKWZWBJtAEGRHVEyFzCtbNl3GPKuDnHBBRT4/nDS4Ru9AIDT72qA==" - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "optional": true - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "devOptional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "optional": true - }, - "ip-address": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-8.1.0.tgz", - "integrity": "sha512-Wz91gZKpNKoXtqvY8ScarKYwhXoK4r/b5QuT+uywe/azv0/nUCo7Bh0IRRI7F9DHR06kJNWtzMGLIbXavngbKA==", - "requires": { - "jsbn": "1.1.0", - "sprintf-js": "1.1.2" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "devOptional": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "requires": { - "append-transform": "^2.0.0" - } - }, - "istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "istanbul-lib-processinfo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", - "dev": true, - "requires": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" - }, - "dependencies": { - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - } - } - }, - "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==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - } - }, - "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", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "js-sdsl": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", - "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsbn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", - "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "dev": true - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha512-hFuH8TY+Yji7Eja3mGiuAxBqLagejScbG8GbG0j6o9vzn0YL14My+ktnqtZgFTosKymC9/44wP6s7xyuLfnClw==" - }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" - }, - "lodash.has": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", - "integrity": "sha512-rnYUdIo6xRCJnQmbVFEwcxF144erlD+M3YcJUVesflU9paQaE8p+fJDcIQrlMYbxoANFL+AB9hZrzSBBk5PL+g==" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", - "dev": true - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "devOptional": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "devOptional": true - } - } - }, - "microformats-parser": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/microformats-parser/-/microformats-parser-1.4.1.tgz", - "integrity": "sha512-BSg9Y/Aik8hvvme/fkxnXMRvTKuVwOeTapeZdaPQ+92DEubyM31iMtwbgFZ1383om643UvfYY5G23E9s1FY2KQ==", - "requires": { - "parse5": "^6.0.0" - } - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "optional": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "devOptional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "optional": true - }, - "minipass": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", - "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", - "optional": true - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "optional": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "optional": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "optional": true - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "optional": true - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "mocha-steps": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/mocha-steps/-/mocha-steps-1.3.0.tgz", - "integrity": "sha512-KZvpMJTqzLZw3mOb+EEuYi4YZS41C9iTnb7skVFRxHjUd1OYbl64tCMSmpdIRM9LnwIrSOaRfPtNpF5msgv6Eg==", - "dev": true - }, - "mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "devOptional": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "optional": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - } - } - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "node-abi": { - "version": "3.33.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.33.0.tgz", - "integrity": "sha512-7GGVawqyHF4pfd0YFybhv/eM9JwTtPqx0mAanQ146O3FlSh3pA24zf9IRQTOsfTSqXTNzPSP5iagAJ94jjuVog==", - "optional": true, - "requires": { - "semver": "^7.3.5" - } - }, - "node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", - "optional": true - }, - "node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "optional": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-linux-pam": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-linux-pam/-/node-linux-pam-0.2.1.tgz", - "integrity": "sha512-OeMZW0Bs1bffsvXI/bJQbU0rkiWTOo0ceT6+mrbU84TJ33vAKykIZrLI+ApfRqkBQW5jzW5rJ7x+NSyToafqig==", - "optional": true, - "requires": { - "@mapbox/node-pre-gyp": "1.0.5", - "bindings": "1.5.0", - "node-addon-api": "3.1.0", - "string-template": "1.0.0", - "yargs": "15.4.1" - }, - "dependencies": { - "@mapbox/node-pre-gyp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", - "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", - "optional": true, - "requires": { - "detect-libc": "^1.0.3", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.1", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "rimraf": "^3.0.2", - "semver": "^7.3.4", - "tar": "^6.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "optional": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "optional": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "optional": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "optional": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "optional": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - } - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "optional": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "node-addon-api": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz", - "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==", - "optional": true - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "optional": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "optional": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "optional": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "optional": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "optional": true, - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "optional": true - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "optional": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "optional": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "requires": { - "process-on-spawn": "^1.0.0" - } - }, - "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", - "dev": true - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "optional": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "optional": true, - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", - "optional": true - }, - "nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, - "requires": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "dependencies": { - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "optional": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "devOptional": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "os-shim": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", - "integrity": "sha512-jd0cvB8qQ5uVt0lvCIexBaROw1KyKm5sbulg2fWOHjETisuCzWyt+eTZKEMs8v6HwzoGs8xik26jg7eCM6pS+A==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "devOptional": true - }, - "package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, - "packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==", - "optional": true - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", - "dev": true, - "requires": { - "no-case": "^2.2.0" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "devOptional": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "devOptional": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true - } - } - }, - "pg": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.10.0.tgz", - "integrity": "sha512-ke7o7qSTMb47iwzOSaZMfeR7xToFdkE71ifIipOAAaLIM0DYzfOAXlgFFmYUIE2BcJtvnVlGCID84ZzCegE8CQ==", - "optional": true, - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.5.0", - "pg-pool": "^3.6.0", - "pg-protocol": "^1.6.0", - "pg-types": "^2.1.0", - "pgpass": "1.x" - } - }, - "pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==", - "optional": true - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "optional": true - }, - "pg-minify": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.3.tgz", - "integrity": "sha512-NoSsPqXxbkD8RIe+peQCqiea4QzXgosdTKY8p7PsbbGsh2F8TifDj/vJxfuR8qJwNYrijdSs7uf0tAe6WOyCsQ==", - "optional": true - }, - "pg-pool": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz", - "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==", - "optional": true, - "requires": {} - }, - "pg-promise": { - "version": "11.4.3", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.4.3.tgz", - "integrity": "sha512-b4wuukB+pkrLRZ53Z+3L9IONlIhOUSM/VlLQV2SnQzNJPJmDZj6ticgcMtZMDanAUEj+zX1FJOBrSpSR9TumXg==", - "optional": true, - "requires": { - "assert-options": "0.8.1", - "pg": "8.10.0", - "pg-minify": "1.6.3", - "spex": "3.3.0" - } - }, - "pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==", - "optional": true - }, - "pg-types": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", - "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", - "optional": true, - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~2.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.4", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", - "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", - "optional": true, - "requires": { - "split2": "^4.1.0" - } - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } - } - }, - "postgres-array": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", - "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", - "optional": true - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", - "optional": true - }, - "postgres-date": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", - "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", - "optional": true - }, - "postgres-interval": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", - "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", - "optional": true, - "requires": { - "xtend": "^4.0.0" - } - }, - "pre-commit": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/pre-commit/-/pre-commit-1.2.2.tgz", - "integrity": "sha512-qokTiqxD6GjODy5ETAIgzsRgnBWWQHQH2ghy86PU7mIn/wuWeTwF3otyNQZxWBwVn8XNr8Tdzj/QfUXpH+gRZA==", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "spawn-sync": "^1.0.15", - "which": "1.2.x" - }, - "dependencies": { - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true - }, - "which": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", - "integrity": "sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", - "dev": true - } - } - }, - "prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", - "optional": true, - "requires": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", - "dev": true, - "requires": { - "fromentries": "^1.2.0" - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "optional": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "regexp-tree": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", - "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", - "dev": true - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "dev": true - }, - "release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "devOptional": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "devOptional": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "devOptional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "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==" - }, - "safe-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", - "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", - "dev": true, - "requires": { - "regexp-tree": "~0.1.1" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "optional": true, - "requires": { - "lru-cache": "^6.0.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==", - "optional": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - } - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "devOptional": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "devOptional": true - }, - "simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "optional": true - }, - "simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", - "optional": true, - "requires": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "sinon": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.0.2.tgz", - "integrity": "sha512-PCVP63XZkg0/LOqQH5rEU4LILuvTFMb5tNxTHfs6VUMNnZz2XrnGSTZbAGITjzwQWbl/Bl/8hi4G3zZWjyBwHg==", - "dev": true, - "requires": { - "@sinonjs/commons": "^3.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/samsam": "^7.0.1", - "diff": "^5.1.0", - "nise": "^5.1.4", - "supports-color": "^7.2.0" - }, - "dependencies": { - "diff": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", - "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", - "dev": true - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "spawn-sync": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", - "integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==", - "dev": true, - "requires": { - "concat-stream": "^1.4.7", - "os-shim": "^0.1.2" - } - }, - "spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "requires": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - } - }, - "spex": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/spex/-/spex-3.3.0.tgz", - "integrity": "sha512-VNiXjFp6R4ldPbVRYbpxlD35yRHceecVXlct1J4/X80KuuPnW2AXMq3sGwhnJOhKkUsOxAT6nRGfGE5pocVw5w==", - "optional": true - }, - "split2": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz", - "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==", - "optional": true - }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-template": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-1.0.0.tgz", - "integrity": "sha512-SLqR3GBUXuoPP5MmYtD7ompvXiG87QjT6lzOszyXjTM86Uu7At7vNnt2xgyTLq5o9T4IxTYFyGxcULqpsmsfdg==", - "optional": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "devOptional": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "devOptional": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", - "optional": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - } - } - }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "optional": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - }, - "dependencies": { - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "optional": true - } - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "optional": true, - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "optional": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "optional": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "optional": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "uglify-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", - "dev": true, - "requires": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - } - } - }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "optional": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "optional": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", - "devOptional": true - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "devOptional": true - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "optional": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - } - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } } } diff --git a/package.json b/package.json index 0fda3cc..8c851b0 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,14 @@ { "name": "@squeep/websub-hub", - "version": "1.3.11", + "version": "1.3.12", "description": "A WebSub Hub server implementation.", "main": "server.js", "scripts": { + "audit": "npm audit", "coverage": "nyc npm test", "coverage-check": "nyc check-coverage", - "eslint": "eslint *.js src", + "eslint": "eslint server.js src", + "eslint:test": "eslint test", "test": "mocha --recursive" }, "repository": { @@ -22,41 +24,40 @@ "syndication" ], "engines": { - "node": ">=14" + "node": ">=20" }, "author": "Justin Wind ", "license": "ISC", "pre-commit": [ "eslint", "coverage", - "coverage-check" + "coverage-check", + "audit" ], "dependencies": { - "@squeep/api-dingus": "git+https://git.squeep.com/squeep-api-dingus/#v1.2.9", - "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.3.0", - "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.4.0", - "@squeep/logger-json-console": "git+https://git.squeep.com/squeep-logger-json-console#v1.0.2", - "@squeep/web-linking": "^1.0.7", - "axios": "^1.3.4", - "feedparser": "^2.2.10", - "htmlparser2": "^8.0.2", - "iconv": "^3.0.1" + "@squeep/api-dingus": "^2", + "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.5.0", + "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.6.1", + "@squeep/logger-json-console": "^3", + "@squeep/roman": "^1", + "@squeep/web-linking": "^1", + "feedparser": "^2", + "got": "^14", + "htmlparser2": "^9", + "iconv": "^3" }, "optionalDependencies": { - "better-sqlite3": "^8.2.0", - "pg-promise": "^11.4.3" + "better-sqlite3": "^11", + "pg-promise": "^11" }, "devDependencies": { - "eslint": "^8.36.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-security": "^1.7.1", - "eslint-plugin-sonarjs": "^0.19.0", - "html-minifier-lint": "^2.0.0", - "mocha": "^10.2.0", - "mocha-steps": "^1.3.0", - "nyc": "^15.1.0", - "pre-commit": "^1.2.2", - "sinon": "^15.0.2" + "@squeep/eslint-config": "^1", + "eslint": "^9", + "html-validate": "^8", + "mocha": "^10", + "mocha-steps": "^1", + "nyc": "^17", + "pre-commit": "^1", + "sinon": "^18" } } diff --git a/server.js b/server.js index 49ce8f6..d5b206c 100644 --- a/server.js +++ b/server.js @@ -1,6 +1,7 @@ 'use strict'; -const http = require('http'); +const http = require('node:http'); +const { AsyncLocalStorage } = require('node:async_hooks'); const DB = require('./src/db'); const Logger = require('./src/logger'); const Service = require('./src/service'); @@ -16,14 +17,19 @@ const ADDR = process.env.LISTEN_ADDR || '127.0.0.1'; (async function main () { let config, logger, db, service; try { + // This provides an async context store for persisting unique log data per request, id est a requestId. + const asyncLocalStorage = new AsyncLocalStorage(); + config = new Config(process.env.NODE_ENV); - logger = new Logger(config); + logger = new Logger(config.logger, { nodeId: config.nodeId }, asyncLocalStorage); db = new DB(logger, config); await db.initialize(); - service = new Service(logger, db, config); + service = new Service(logger, db, config, asyncLocalStorage); - http.createServer((req, res) => { - service.dispatch(req, res); + http.createServer(async (req, res) => { + await asyncLocalStorage.run({}, async () => { + return service.dispatch(req, res); + }); }).listen(PORT, ADDR, (err) => { if (err) { logger.error(_scope, 'error creating server', err); @@ -33,6 +39,6 @@ const ADDR = process.env.LISTEN_ADDR || '127.0.0.1'; }); } catch (e) { (logger || console).error(_scope, 'error starting server', e); - db && db.listener && await db.listener.stop(); + db?.listener && await db.listener.stop(); } })(); \ No newline at end of file diff --git a/src/common.js b/src/common.js index 4ed310f..0d6500c 100644 --- a/src/common.js +++ b/src/common.js @@ -19,17 +19,18 @@ const randomBytesAsync = promisify(randomBytes); /** * The HMAC hashes we are willing to support. - * @param {String} algorithm - * @returns {Boolean} + * @param {string} algorithm potential sha* algorithm + * @returns {boolean} is supported */ const validHash = (algorithm) => getHashes() - .filter((h) => h.match(/^sha[0-9]+$/)) + .filter((h) => h.match(/^sha\d+$/)) .includes(algorithm); /** * Return an array containing x if x is not an array. - * @param {*} x + * @param {*} x possibly an array + * @returns {Array} x or [x] */ const ensureArray = (x) => { if (x === undefined) { @@ -44,13 +45,13 @@ const ensureArray = (x) => { /** * Recursively freeze an object. - * @param {Object} o - * @returns {Object} + * @param {object} o object + * @returns {object} frozen object */ const freezeDeep = (o) => { Object.freeze(o); Object.getOwnPropertyNames(o).forEach((prop) => { - if (Object.hasOwnProperty.call(o, prop) + if (Object.hasOwn(o, prop) && ['object', 'function'].includes(typeof o[prop]) && !Object.isFrozen(o[prop])) { return freezeDeep(o[prop]); @@ -61,20 +62,31 @@ const freezeDeep = (o) => { /** - * Pick out useful axios response fields. - * @param {*} res - * @returns + * Pick out useful got response fields. + * @param {*} res response + * @returns {object} winnowed response */ -const axiosResponseLogData = (res) => { +const gotResponseLogData = (res) => { const data = common.pick(res, [ - 'status', - 'statusText', + 'statusCode', + 'statusMessage', 'headers', - 'elapsedTimeMs', - 'data', + 'body', + 'error', ]); - if (data.data) { - data.data = logTruncate(data.data, 100); + if (typeof res.body === 'string') { + data.body = logTruncate(data.body, 100); + } else if (res.body instanceof Buffer) { + data.body = ``; + } + if (res?.timings?.phases?.total) { + data.elapsedTimeMs = res.timings.phases.total; + } + if (res?.redirectUrls?.length) { + data.redirectUrls = res.redirectUrls; + } + if (res?.retryCount) { + data.retryCount = res.retryCount; } return data; }; @@ -82,7 +94,7 @@ const axiosResponseLogData = (res) => { /** * Fallback values, if not configured. - * @returns {Object} + * @returns {object} object */ const topicLeaseDefaults = () => { return Object.freeze({ @@ -95,10 +107,10 @@ const topicLeaseDefaults = () => { /** * Pick from a range, constrained, with some fuzziness. - * @param {Number} attempt - * @param {Number[]} delays - * @param {Number} jitter - * @returns {Number} + * @param {number} attempt attempt number + * @param {number[]=} retryBackoffSeconds array of indexed delays + * @param {number=} jitter vary backoff by up to this fraction additional + * @returns {number} seconds to delay retry */ const attemptRetrySeconds = (attempt, retryBackoffSeconds = [60, 120, 360, 1440, 7200, 43200, 86400], jitter = 0.618) => { const maxAttempt = retryBackoffSeconds.length - 1; @@ -107,7 +119,7 @@ const attemptRetrySeconds = (attempt, retryBackoffSeconds = [60, 120, 360, 1440, } else if (attempt > maxAttempt) { attempt = maxAttempt; } - // eslint-disable-next-line security/detect-object-injection + let seconds = retryBackoffSeconds[attempt]; seconds += Math.floor(Math.random() * seconds * jitter); return seconds; @@ -116,8 +128,9 @@ const attemptRetrySeconds = (attempt, retryBackoffSeconds = [60, 120, 360, 1440, /** * Return array items split as an array of arrays of no more than per items each. - * @param {Array} array - * @param {Number} per + * @param {Array} array items + * @param {number} per chunk size + * @returns {Array[]} array of chunks */ const arrayChunk = (array, per = 1) => { const nChunks = Math.ceil(array.length / per); @@ -127,8 +140,8 @@ const arrayChunk = (array, per = 1) => { /** * Be paranoid about blowing the stack when pushing to an array. - * @param {Array} dst - * @param {Array} src + * @param {Array} dst destination array + * @param {Array} src source array */ const stackSafePush = (dst, src) => { const jsEngineMaxArguments = 2**16; // Current as of Node 12 @@ -140,9 +153,9 @@ const stackSafePush = (dst, src) => { /** * Limit length of string to keep logs sane - * @param {String} str - * @param {Number} len - * @returns {String} + * @param {string} str string + * @param {number} len max length + * @returns {string} truncated string */ const logTruncate = (str, len) => { if (typeof str !== 'string' || str.toString().length <= len) { @@ -151,14 +164,17 @@ const logTruncate = (str, len) => { return str.toString().slice(0, len) + `... (${str.toString().length} bytes)`; }; +const nop = () => undefined; + module.exports = { ...common, arrayChunk, attemptRetrySeconds, - axiosResponseLogData, + gotResponseLogData, ensureArray, freezeDeep, logTruncate, + nop, randomBytesAsync, stackSafePush, topicLeaseDefaults, diff --git a/src/communication.js b/src/communication.js index feda588..9a4da3a 100644 --- a/src/communication.js +++ b/src/communication.js @@ -5,7 +5,6 @@ * worker which initiates most of them. */ -const axios = require('axios'); const common = require('./common'); const crypto = require('crypto'); const Enum = require('./enum'); @@ -14,8 +13,6 @@ const Worker = require('./worker'); const LinkHelper = require('./link-helper'); const { version: packageVersion, name: packageName } = require('../package.json'); // For default UA string -const { performance } = require('perf_hooks'); - const _fileScope = common.fileScope(__filename); class Communication { @@ -32,28 +29,68 @@ class Communication { this.logger.error(_fileScope('constructor'), 'empty dingus.selfBaseUrl value, server responses will not be compliant'); } - // Set common options - this.axios = axios.create({ - validateStatus: null, // Non-success responses are not exceptional - headers: { - [Enum.Header.UserAgent]: Communication.userAgentString(options.userAgent), - }, - }); - - this.axios.interceptors.request.use((request) => { - request.startTimestampMs = performance.now(); - return request; - }); - this.axios.interceptors.response.use((response) => { - response.elapsedTimeMs = performance.now() - response.config.startTimestampMs; - return response; - }); + this.Got = undefined; // Will become the async imported got. + this.got = this._init; // First invocation imports got and replaces this. this.worker = new Worker(logger, db, this.workFeed.bind(this), options); this.worker.start(); } + /** + * Do a little dance to cope with ESM dynamic import. + * @param {...any} args arguments + * @returns {Promise} got response + */ + async _init(...args) { + if (!this.Got) { + // For some reason eslint is confused about import being supported here. + + this.Got = await import('got'); + this.got = this.Got.got.extend({ + followRedirect: false, // Outgoing API calls should not encounter redirects + throwHttpErrors: false, // We will be checking status codes explicitly + headers: { + [Enum.Header.UserAgent]: Communication.userAgentString(this.options.userAgent), + }, + timeout: { + request: this.options.communication.requestTimeoutMs || 120000, + }, + hooks: { + beforeRetry: [ + this._onRetry, + ], + }, + }); + } + + /* istanbul ignore if */ + if (args.length) { + /* istanbul ignore next */ + return this.got(...args); + } + } + + + /** + * Take note of transient retries. + * @param {*} error error + * @param {*} retryCount retry count + */ + _onRetry(error, retryCount) { + const _scope = _fileScope('_onRetry'); + this.logger.debug(_scope, 'retry', { retryCount, error }); + } + + + /** + * Construct a user-agent value. + * @param {object} userAgentConfig user agent config + * @param {string=} userAgentConfig.product product name (default package name) + * @param {string=} userAgentConfig.version version (default package version) + * @param {string=} userAgentConfig.implementation implementation (default spec supported) + * @returns {string} user agent string 'product/version (implementation)' + */ static userAgentString(userAgentConfig) { // eslint-disable-next-line security/detect-object-injection const _conf = (field, def) => (userAgentConfig && field in userAgentConfig) ? userAgentConfig[field] : def; @@ -67,10 +104,13 @@ class Communication { } + /** + * @alias {number} Integer + */ /** * Generate a random string. - * @param {Integer} bytes - * @returns {String} + * @param {Integer} bytes size of challenge + * @returns {Promise} base64 randomness */ static async generateChallenge(bytes = 30) { return (await common.randomBytesAsync(bytes)).toString('base64'); @@ -79,135 +119,38 @@ class Communication { /** * Generate the signature string for content. - * @param {Buffer} message - * @param {Buffer} secret - * @param {String} algorithm - * @returns {String} + * @param {Buffer} message message to sign + * @param {Buffer} secret secret to sign with + * @param {string} algorithm algorithm to sign with + * @returns {string} signature string */ static signature(message, secret, algorithm) { - const hmac = crypto.createHmac(algorithm, secret); - hmac.update(message); - return `${algorithm}=${hmac.digest('hex')}`; + const hmac = crypto.createHmac(algorithm, secret) + .update(message) + .digest('hex'); + return `${algorithm}=${hmac}`; } /** * Generate the hash for content. - * @param {Buffer} content - * @param {String} algorithm - * @returns + * @param {Buffer} content content + * @param {string} algorithm algorithm + * @returns {string} hash of content */ static contentHash(content, algorithm) { - const hash = crypto.createHash(algorithm); - hash.update(content); - return hash.digest('hex'); - } - - - /** - * A request skeleton config. - * @param {String} method - * @param {String} requestUrl - * @param {String} body - * @param {Object} params - */ - static _axiosConfig(method, requestUrl, body, params = {}, headers = {}) { - const urlObj = new URL(requestUrl); - const config = { - method, - url: `${urlObj.origin}${urlObj.pathname}`, - params: urlObj.searchParams, - headers, - ...(body && { data: body }), - // Setting this does not appear to be enough to keep axios from parsing JSON response into object - responseType: 'text', - // So force the matter by eliding all response transformations - transformResponse: [ (res) => res ], - }; - Object.entries(params).map(([k, v]) => config.params.set(k, v)); - return config; - } - - - /** - * Create request config for verifying an intent. - * @param {URL} requestUrl - * @param {String} topicUrl - * @param {String} mode - * @param {Integer} leaseSeconds - * @param {String} challenge - */ - static _intentVerifyAxiosConfig(requestUrl, topicUrl, mode, leaseSeconds, challenge) { - // Explicitly convert leaseSeconds to string, due to some DB backends. (Looking at you, sqlite..) - leaseSeconds = leaseSeconds.toString(); - - return Communication._axiosConfig('GET', requestUrl, undefined, { - 'hub.mode': mode, - 'hub.topic': topicUrl, - 'hub.challenge': challenge, - 'hub.lease_seconds': leaseSeconds, - }, {}); - } - - - /** - * Create request config for denying an intent. - * @param {String} requestUrl - * @param {String} topicUrl - * @param {String} reason - * @returns {String} - */ - static _intentDenyAxiosConfig(requestUrl, topicUrl, reason) { - return Communication._axiosConfig('GET', requestUrl, undefined, { - 'hub.mode': Enum.Mode.Denied, - 'hub.topic': topicUrl, - ...(reason && { 'hub.reason': reason }), - }, {}); - } - - - /** - * Create request config for querying publisher for subscription validation. - * @param {Topic} topic - * @param {Verification} verification - * @returns {String} - */ - static _publisherValidationAxiosConfig(topic, verification) { - const body = { - callback: verification.callback, - topic: topic.url, - ...(verification.httpFrom && { from: verification.httpFrom }), - ...(verification.httpRemoteAddr && { address: verification.httpRemoteAddr }), - }; - return Communication._axiosConfig('POST', topic.publisherValidationUrl, body, {}, { - [Enum.Header.ContentType]: Enum.ContentType.ApplicationJson, - }); - } - - - /** - * Create request config for fetching topic content. - * Prefer existing content-type, but accept anything. - * @param {Topic} topic - * @returns {String} - */ - static _topicFetchAxiosConfig(topic) { - const acceptWildcard = '*/*' + (topic.contentType ? ';q=0.9' : ''); - const acceptPreferred = [topic.contentType, acceptWildcard].filter((x) => x).join(', '); - return Communication._axiosConfig('GET', topic.url, undefined, {}, { - [Enum.Header.Accept]: acceptPreferred, - ...(topic.httpEtag && { [Enum.Header.IfNoneMatch]: topic.httpEtag }), - ...(topic.httpLastModified && { [Enum.Header.IfModifiedSince]: topic.httpLastModified }), - }); + return crypto.createHash(algorithm) + .update(content) + .digest('hex'); } /** * Attempt to verify a requested intent with client callback endpoint. - * @param {*} dbCtx - * @param {*} verificationId - * @param {String} requestId - * @returns {Boolean} whether to subsequently attempt next task if verification succeeds + * @param {*} dbCtx db context + * @param {*} verificationId verification id + * @param {string} requestId request id + * @returns {Promise} whether to subsequently attempt next task if verification succeeds */ async verificationProcess(dbCtx, verificationId, requestId) { const _scope = _fileScope('verificationProcess'); @@ -256,19 +199,37 @@ class Communication { } } - const u = new URL(verification.callback); - let callbackRequestConfig, challenge; + const callbackRequestConfig = { + method: 'GET', + url: new URL(verification.callback), + responseType: 'text', + }; + const callbackParams = { + 'hub.topic': topic.url, + 'hub.mode': verification.mode, + }; + + let challenge; if (verification.mode === Enum.Mode.Denied) { - // Denials don't have a challenge. - callbackRequestConfig = Communication._intentDenyAxiosConfig(u, topic.url, verification.reason); + // Denials don't have a challenge, but might have a reason. + if (verification.reason) { + callbackParams['hub.reason'] = verification.reason; + } } else { // Subscriptions and unsubscriptions require challenge matching. challenge = await Communication.generateChallenge(); - callbackRequestConfig = Communication._intentVerifyAxiosConfig(u, topic.url, verification.mode, verification.leaseSeconds, challenge); + Object.assign(callbackParams, { + 'hub.challenge': challenge, + // Explicitly convert leaseSeconds to string, due to some DB backends. (Looking at you, sqlite..) + 'hub.lease_seconds': verification.leaseSeconds.toString(), + }); } + Object.entries(callbackParams) + .forEach(([k, v]) => callbackRequestConfig.url.searchParams.set(k, v)) + ; const logInfoData = { - callbackUrl: u.href, + callbackUrl: callbackRequestConfig.url.href, topicUrl: topic.url, mode: verification.mode, originalRequestId: verification.requestId, @@ -280,18 +241,18 @@ class Communication { let response; try { - response = await this.axios(callbackRequestConfig); + response = await this.got(callbackRequestConfig); } catch (e) { this.logger.error(_scope, 'verification request failed', { ...logInfoData, error: e }); await this.db.verificationIncomplete(dbCtx, verificationId, this.options.communication.retryBackoffSeconds); return; } - logInfoData.response = common.axiosResponseLogData(response); + logInfoData.response = common.gotResponseLogData(response); this.logger.debug(_scope, 'verification response', logInfoData ); let verificationAccepted = true; // Presume success. - switch (common.httpStatusCodeClass(response.status)) { + switch (common.httpStatusCodeClass(response.statusCode)) { case 2: // Success, fall out of switch. break; @@ -315,7 +276,7 @@ class Communication { } if ([Enum.Mode.Subscribe, Enum.Mode.Unsubscribe].includes(verification.mode) - && response.data !== challenge) { + && response.body !== challenge) { this.logger.info(_scope, 'verification rejected by challenge', logInfoData); verificationAccepted = false; } @@ -341,7 +302,7 @@ class Communication { case Enum.Mode.Denied: await this.db.subscriptionDelete(txCtx, verification.callback, verification.topicId); if (topic.isDeleted) { - // Remove a deleted topic after he last subscription is notified. + // Remove a deleted topic after the last subscription is notified. await this.db.topicPendingDelete(txCtx, topic.id); } break; @@ -358,19 +319,24 @@ class Communication { } + /** + * @alias {object} TopicData + * @alias {object} VerificationData + */ /** * Attempt to verify a pending subscription request with publisher. * Updates (and persists) verification. * Returns boolean of status of publisher contact, and hence * whether to continue verification with client. - * @param {*} dbCtx - * @param {TopicData} topic - * @param {VerificationData} verification - * @returns {Boolean} + * + * This is not defined by the spec. We opt to speak JSON here. + * @param {*} dbCtx db context + * @param {TopicData} topic topic + * @param {VerificationData} verification verification + * @returns {Promise} true if successful contact with publisher */ async publisherValidate(dbCtx, topic, verification) { const _scope = _fileScope('publisherValidate'); - const publisherValidationRequestConfig = Communication._publisherValidationAxiosConfig(topic, verification); const logInfoData = { topicUrl: topic.url, callbackUrl: verification.callback, @@ -380,18 +346,29 @@ class Communication { this.logger.info(_scope, 'publisher validation request', logInfoData); + const publisherValidationRequestConfig = { + method: 'POST', + url: topic.publisherValidationUrl, + json: { + callback: verification.callback, + topic: topic.url, + ...(verification.httpFrom && { from: verification.httpFrom }), + ...(verification.httpRemoteAddr && { address: verification.httpRemoteAddr }), + }, + responseType: 'json', + }; try { - response = await this.axios(publisherValidationRequestConfig); + response = await this.got(publisherValidationRequestConfig); } catch (e) { this.logger.error(_scope, 'publisher validation failed', { ...logInfoData, error: e }); return false; // Do not continue with client verification. } - logInfoData.response = common.axiosResponseLogData(response); + logInfoData.response = common.gotResponseLogData(response); this.logger.debug(_scope, 'validation response', logInfoData); let verificationNeedsUpdate = false; - switch (common.httpStatusCodeClass(response.status)) { + switch (common.httpStatusCodeClass(response.statusCode)) { case 2: this.logger.info(_scope, 'publisher validation complete, allowed', logInfoData); break; @@ -422,10 +399,10 @@ class Communication { /** * Retrieve content from a topic. - * @param {*} dbCtx - * @param {*} topicId - * @param {String} requestId - * @returns + * @param {*} dbCtx db context + * @param {*} topicId topic id + * @param {string} requestId request id + * @returns {Promise} */ async topicFetchProcess(dbCtx, topicId, requestId) { const _scope = _fileScope('topicFetchProcess'); @@ -452,22 +429,32 @@ class Communication { return; } - const updateRequestConfig = Communication._topicFetchAxiosConfig(topic); + const updateRequestConfig = { + followRedirect: true, + method: 'GET', + url: topic.url, + headers: { + [Enum.Header.Accept]: [topic.contentType, `*/*${topic.contentType ? ';q=0.9' : ''}`].filter((x) => x).join(', '), + ...(topic.httpEtag && { [Enum.Header.IfNoneMatch]: topic.httpEtag }), + ...(topic.httpLastModified && { [Enum.Header.IfModifiedSince]: topic.httpLastModified }), + }, + responseType: 'buffer', + }; this.logger.info(_scope, 'topic update request', logInfoData); let response; try { - response = await this.axios(updateRequestConfig); + response = await this.got(updateRequestConfig); } catch (e) { - this.logger.error(_scope, 'update request failed', logInfoData); + this.logger.error(_scope, 'update request failed', { ...logInfoData, error: e }); await this.db.topicFetchIncomplete(dbCtx, topicId, this.options.communication.retryBackoffSeconds); return; } - logInfoData.response = common.axiosResponseLogData(response); + logInfoData.response = common.gotResponseLogData(response); this.logger.debug(_scope, 'fetch response', logInfoData); - switch (common.httpStatusCodeClass(response.status)) { + switch (common.httpStatusCodeClass(response.statusCode)) { case 2: case 3: // Fall out of switch on success @@ -484,13 +471,13 @@ class Communication { return; } - if (response.status === 304) { + if (response.statusCode === 304) { this.logger.info(_scope, 'content has not changed, per server', logInfoData); await this.db.topicFetchComplete(dbCtx, topicId); return; } - const contentHash = Communication.contentHash(response.data, topic.contentHashAlgorithm); + const contentHash = Communication.contentHash(response.body, topic.contentHashAlgorithm); logInfoData.contentHash = contentHash; if (topic.contentHash === contentHash) { this.logger.info(_scope, 'content has not changed', logInfoData); @@ -498,7 +485,7 @@ class Communication { return; } - const validHub = await this.linkHelper.validHub(topic.url, response.headers, response.data); + const validHub = await this.linkHelper.validHub(topic.url, response.headers, response.body); if (!validHub) { this.logger.info(_scope, 'retrieved topic does not list us as hub', { logInfoData }); if (this.options.communication.strictTopicHubLink) { @@ -520,7 +507,7 @@ class Communication { await this.db.transaction(dbCtx, async (txCtx) => { await this.db.topicSetContent(txCtx, { topicId, - content: Buffer.from(response.data), + content: Buffer.from(response.body), contentHash, ...(contentType && { contentType }), ...(httpETag && { httpETag }), @@ -535,10 +522,10 @@ class Communication { /** * Attempt to deliver a topic's content to a subscription. - * @param {*} dbCtx - * @param {String} callback - * @param {*} topicId - * @param {String} requestId + * @param {*} dbCtx db context + * @param {string} subscriptionId subscription id + * @param {string} requestId request id + * @returns {Promise} */ async subscriptionDeliveryProcess(dbCtx, subscriptionId, requestId) { const _scope = _fileScope('subscriptionDeliveryProcess'); @@ -587,26 +574,32 @@ class Communication { logInfoData.contentLength = topic.content.length; logInfoData.contentHash = topic.contentHash; - const updateAxiosConfig = Communication._axiosConfig('POST', subscription.callback, topic.content, {}, { - [Enum.Header.Link]: `<${topic.url}>; rel="self"${this.linkHub}`, - [Enum.Header.ContentType]: topic.contentType || Enum.ContentType.TextPlain, - ...(subscription.secret && { [Enum.Header.XHubSignature]: Communication.signature(topic.content, subscription.secret, subscription.signatureAlgorithm) }), - }); + const updateConfig = { + method: 'POST', + url: subscription.callback, + body: topic.content, + headers: { + [Enum.Header.Link]: `<${topic.url}>; rel="self"${this.linkHub}`, + [Enum.Header.ContentType]: topic.contentType || Enum.ContentType.TextPlain, + ...(subscription.secret && { [Enum.Header.XHubSignature]: Communication.signature(topic.content, subscription.secret, subscription.signatureAlgorithm) }), + }, + responseType: 'text', + }; this.logger.info(_scope, 'update request', logInfoData); let response; try { - response = await this.axios(updateAxiosConfig); + response = await this.got(updateConfig); } catch (e) { this.logger.error(_scope, 'update request failed', { ...logInfoData, error: e }); await this.db.subscriptionDeliveryIncomplete(dbCtx, subscription.callback, subscription.topicId, this.options.communication.retryBackoffSeconds); return; } - logInfoData.response = common.axiosResponseLogData(response); + logInfoData.response = common.gotResponseLogData(response); this.logger.debug(_scope, 'update response', logInfoData); - switch (common.httpStatusCodeClass(response.status)) { + switch (common.httpStatusCodeClass(response.statusCode)) { case 2: // Fall out of switch on success. break; @@ -617,7 +610,7 @@ class Communication { return; case 4: - if (response.status === 410) { // GONE + if (response.statusCode === 410) { // GONE this.logger.info(_scope, 'client declined further updates', logInfoData); await this.db.subscriptionDeliveryGone(dbCtx, subscription.callback, subscription.topicId); return; @@ -637,9 +630,10 @@ class Communication { /** * Claim and work a specific topic fetch task. - * @param {*} dbCtx - * @param {*} id - * @param {String} requestId + * @param {*} dbCtx db context + * @param {string} topicId topic id + * @param {string} requestId request id + * @returns {Promise} */ async topicFetchClaimAndProcessById(dbCtx, topicId, requestId) { const _scope = _fileScope('topicFetchClaimAndProcessById'); @@ -655,10 +649,10 @@ class Communication { /** * Claim and work a specific verification confirmation task. - * @param {*} dbCtx - * @param {*} verificationId - * @param {String} requestId - * @returns + * @param {*} dbCtx db context + * @param {*} verificationId verification id + * @param {string} requestId request id + * @returns {Promise} whether to subsequently attempt next task if verification succeeds */ async verificationClaimAndProcessById(dbCtx, verificationId, requestId) { const _scope = _fileScope('verificationClaimAndProcessById'); @@ -674,9 +668,9 @@ class Communication { /** * - * @param {*} dbCtx - * @param {Number} wanted maximum tasks to claim - * @returns {Promise[]} + * @param {*} dbCtx db context + * @param {number} wanted maximum tasks to claim + * @returns {Promise[]} array of promises processing work */ async workFeed(dbCtx, wanted) { const _scope = _fileScope('workFeed'); diff --git a/src/db/base.js b/src/db/base.js index 205b814..8331fb2 100644 --- a/src/db/base.js +++ b/src/db/base.js @@ -12,9 +12,8 @@ const svh = require('./schema-version-helper'); const _fileScope = common.fileScope(__filename); class Database { - constructor(logger = common.nullLogger, options = {}) { + constructor(logger, options = {}) { this.logger = logger; - common.ensureLoggerLevels(this.logger); // Store the merged config and default values for lease values. // N.B. breaking hierarchy of config options here @@ -26,9 +25,9 @@ class Database { /** * Turn a snake into a camel. * Used when translating SQL column names to JS object style. - * @param {String} snakeCase - * @param {String|RegExp} delimiter - * @returns {String} + * @param {string} snakeCase snake case string + * @param {string | RegExp} delimiter default '_' + * @returns {string} camelCaseString */ static _camelfy(snakeCase, delimiter = '_') { if (!snakeCase || typeof snakeCase.split !== 'function') { @@ -44,9 +43,9 @@ class Database { /** * Basic type checking of object properties. - * @param {Object} object - * @param {String[]} properties - * @param {String[]} types + * @param {object} object object + * @param {string[]} properties list of property names + * @param {string[]} types list of valid types for property names */ _ensureTypes(object, properties, types) { const _scope = _fileScope('_ensureTypes'); @@ -73,8 +72,8 @@ class Database { /** * Interface methods need implementations. - * @param {String} method - * @param {arguments} args + * @param {string} method method name + * @param {arguments} args arguments */ _notImplemented(method, args) { this.logger.error(_fileScope(method), 'abstract method called', Array.from(args)); @@ -88,7 +87,8 @@ class Database { * At the minimum, this will validate a compatible schema is present and usable. * Some engines will also perform other initializations or async actions which * are easier handled outside the constructor. - */ + * @returns {Promise} + */ async initialize() { const _scope = _fileScope('initialize'); @@ -107,6 +107,7 @@ class Database { /** * Perform db connection healthcheck. + * @returns {Promise} */ async healthCheck() { this._notImplemented('healthCheck', arguments); @@ -115,8 +116,8 @@ class Database { /** * Replace any NULL from topic DB entry with default values. - * @param {Object} topic - * @returns {Object} + * @param {object} topic topic entry + * @returns {object} updated topic entry */ _topicDefaults(topic) { if (topic) { @@ -134,7 +135,7 @@ class Database { /** * Ensures any lease durations in data are consistent. - * @param {Object} data + * @param {object} data topic data */ _leaseDurationsValidate(data) { const leaseProperties = Object.keys(this.topicLeaseDefaults); @@ -156,7 +157,7 @@ class Database { /** * Basic field validation for setting topic data. - * @param {Object} data + * @param {object} data topic data */ _topicSetDataValidate(data) { this._ensureTypes(data, ['url'], ['string']); @@ -167,7 +168,7 @@ class Database { /** * Basic field validation for setting topic content. - * @param {Object} data + * @param {object} data topic data */ _topicSetContentDataValidate(data) { this._ensureTypes(data, ['content'], ['string', 'buffer']); @@ -180,7 +181,7 @@ class Database { /** * Basic field validation for updating topic. - * @param {Object} data + * @param {object} data topic data */ _topicUpdateDataValidate(data) { this._ensureTypes(data, ['publisherValidationUrl'], ['string', 'undefined', 'null']); @@ -201,7 +202,7 @@ class Database { /** * Basic field validation for setting verification data. - * @param {Object} data + * @param {object} data topic data */ _verificationDataValidate(data) { this._ensureTypes(data, ['topicId'], ['string', 'number']); @@ -214,7 +215,7 @@ class Database { /** * Basic field validation for updating verification data. - * @param {Object} verification + * @param {object} data verification data */ _verificationUpdateDataValidate(data) { this._ensureTypes(data, ['verificationId'], ['string', 'number']); @@ -226,7 +227,7 @@ class Database { /** * Basic field validation for upserting subscription data. - * @param {Object} subscription + * @param {object} data subscription data */ _subscriptionUpsertDataValidate(data) { this._ensureTypes(data, ['topicId'], ['string', 'number']); @@ -236,6 +237,10 @@ class Database { } + /** + * Basic field validation for subscription update data. + * @param {object} data subscription data + */ _subscriptionUpdateDataValidate(data) { this._ensureTypes(data, ['signatureAlgorithm'], ['string', 'null', 'undefined']); if (!common.validHash(data.signatureAlgorithm)) { @@ -246,26 +251,31 @@ class Database { /* Interface methods */ + /** + * @typedef {object} CommonDBInfo + * @property {number} changes result changes + * @property {*} lastInsertRowid result row id + * @property {number} duration result duration + */ /** * Normalize query information to a common form from a specific backend. - * @param {*} result - * @returns {Object} info - * @returns {Number} info.changes - * @returns {*} info.lastInsertRowid - * @returns {Number} info.duration + * @param {*} result db result */ _engineInfo(result) { this._notImplemented('engineInfo', arguments); } + /** + * @typedef {object} SchemaVersion + * @property {number} major semver major + * @property {number} minor semver minor + * @property {number} patch semver patch + */ /** * Query the current schema version. * This is a standalone query function, as it is called before statements are loaded. - * @returns {Object} version - * @returns {Number} version.major - * @returns {Number} version.minor - * @returns {Number} version.patch + * @returns {SchemaVersion} schema version */ async _currentSchema() { this._notImplemented('_currentSchema', arguments); @@ -283,7 +293,7 @@ class Database { /** * Wrap a function call in a transaction context. - * @param {*} dbCtx + * @param {*} dbCtx db context * @param {Function} fn fn(txCtx) */ async transaction(dbCtx, fn) { @@ -293,8 +303,8 @@ class Database { /** * Store an authentication success event. - * @param {*} dbCtx - * @param {String} identifier + * @param {*} dbCtx db context + * @param {string} identifier authentication identifier */ async authenticationSuccess(dbCtx, identifier) { this._notImplemented('authenticationSuccess', arguments); @@ -303,8 +313,8 @@ class Database { /** * Fetch authentication data for identifier. - * @param {*} dbCtx - * @param {*} identifier + * @param {*} dbCtx db context + * @param {*} identifier authentication identifier */ async authenticationGet(dbCtx, identifier) { this._notImplemented('authenticationGet', arguments); @@ -313,19 +323,42 @@ class Database { /** * Create or update an authentication entity. - * @param {*} dbCtx - * @param {String} identifier - * @param {String} credential + * @param {*} dbCtx db context + * @param {string} identifier authentication identifier + * @param {string} credential authentication credential + * @param {string=} otpKey authentication otp key */ - async authenticationUpsert(dbCtx, identifier, credential) { + async authenticationUpsert(dbCtx, identifier, credential, otpKey) { this._notImplemented('authenticationUpsert', arguments); } + /** + * Update an authentication entity's otp key. + * @param {*} dbCtx db context + * @param {string} identifier authentication identifier + * @param {string=} otpKey authentication otp key + */ + async authenticationUpdateOTPKey(dbCtx, identifier, otpKey) { + this._notImplemented('authenticationUpdateKey', arguments); + } + + + /** + * Update an authentication entity's credential. + * @param {*} dbCtx db context + * @param {string} identifier authentication identifier + * @param {string} credential authentication credential + */ + async authenticationUpdateCredential(dbCtx, identifier, credential) { + this._notImplemented('authenticationUpdateKey', arguments); + } + + /** * All subscriptions to a topic. - * @param {*} dbCtx - * @param {String} topicId + * @param {*} dbCtx db context + * @param {string} topicId topic id */ async subscriptionsByTopicId(dbCtx, topicId) { this._notImplemented('subscriptionsByTopicId', arguments); @@ -334,8 +367,8 @@ class Database { /** * Number of subscriptions to a topic. - * @param {*} dbCtx - * @param {String} topicUrl + * @param {*} dbCtx db context + * @param {string} topicUrl topic url */ async subscriptionCountByTopicUrl(dbCtx, topicUrl) { this._notImplemented('subscriptionCountByTopicUrl', arguments); @@ -344,9 +377,9 @@ class Database { /** * Remove an existing subscription. - * @param {*} dbCtx - * @param {String} callback - * @param {*} topicId + * @param {*} dbCtx db context + * @param {string} callback subscriber callback url + * @param {*} topicId topic id */ async subscriptionDelete(dbCtx, callback, topicId) { this._notImplemented('subscriptionDelete', arguments); @@ -355,20 +388,23 @@ class Database { /** * Remove any expired subscriptions to a topic. - * @param {*} dbCtx - * @param {*} topicId + * @param {*} dbCtx db context + * @param {*} topicId topic id */ async subscriptionDeleteExpired(dbCtx, topicId) { this._notImplemented('subscriptionDeleteExpired', arguments); } + /** + * @alias {number} Integer + */ /** * Claim subscriptions needing content updates attempted. - * @param {*} dbCtx - * @param {Number} wanted maximum subscription updates to claim + * @param {*} dbCtx db context + * @param {number} wanted maximum subscription updates to claim * @param {Integer} claimTimeoutSeconds age of claimed updates to reclaim - * @param {String} claimant + * @param {string} claimant worker claiming processing * @returns {Array} list of subscriptions */ async subscriptionDeliveryClaim(dbCtx, wanted, claimTimeoutSeconds, claimant) { @@ -378,10 +414,10 @@ class Database { /** * Claim a subscription delivery. - * @param {*} dbCtx - * @param {*} subscriptionId - * @param {*} claimTimeoutSeconds - * @param {*} claimant + * @param {*} dbCtx db context + * @param {*} subscriptionId subscription id + * @param {number} claimTimeoutSeconds duration of claim + * @param {*} claimant worker claiming processing */ async subscriptionDeliveryClaimById(dbCtx, subscriptionId, claimTimeoutSeconds, claimant) { this._notImplemented('subscriptionDeliveryClaimById', arguments); @@ -390,9 +426,9 @@ class Database { /** * A subscriber successfully received new topic content, update subscription. - * @param {*} dbCtx - * @param {String} callback - * @param {*} topicId + * @param {*} dbCtx db context + * @param {string} callback subscriber callback url + * @param {*} topicId topic id */ async subscriptionDeliveryComplete(dbCtx, callback, topicId) { this._notImplemented('subscriptionDeliveryComplete', arguments); @@ -401,9 +437,9 @@ class Database { /** * A subscriber denied new topic content, remove subscription. - * @param {*} dbCtx - * @param {String} callback - * @param {*} topicId + * @param {*} dbCtx db context + * @param {string} callback subscriber callback url + * @param {*} topicId topic id */ async subscriptionDeliveryGone(dbCtx, callback, topicId) { this._notImplemented('subscriptionDeliveryGone', arguments); @@ -412,10 +448,10 @@ class Database { /** * An attempt to deliver content to a subscriber did not complete, update delivery accordingly. - * @param {*} dbCtx - * @param {String} callback - * @param {*} topicId - * @param {Number[]} retryDelays + * @param {*} dbCtx db context + * @param {string} callback subscriber callback url + * @param {*} topicId topic id + * @param {number[]} retryDelays list of retry delays */ async subscriptionDeliveryIncomplete(dbCtx, callback, topicId, retryDelays) { this._notImplemented('subscriptionDeliveryIncomplete', arguments); @@ -424,9 +460,9 @@ class Database { /** * Fetch subscription details - * @param {*} dbCtx - * @param {String} callback - * @param {*} topicId + * @param {*} dbCtx db context + * @param {string} callback subscriber callback url + * @param {*} topicId topic id */ async subscriptionGet(dbCtx, callback, topicId) { this._notImplemented('subscriptionGet', arguments); @@ -435,8 +471,8 @@ class Database { /** * Fetch subscription details - * @param {*} dbCtx - * @param {*} subscriptionId + * @param {*} dbCtx db context + * @param {*} subscriptionId subscription id */ async subscriptionGetById(dbCtx, subscriptionId) { this._notImplemented('subscriptionGetById', arguments); @@ -445,14 +481,14 @@ class Database { /** * Set subscription details - * @param {*} dbCtx - * @param {Object} data - * @param {String} data.callback - * @param {*} data.topicId - * @param {Number} data.leaseSeconds - * @param {String=} data.secret - * @param {String=} data.httpRemoteAddr - * @param {String=} data.httpFrom + * @param {*} dbCtx db context + * @param {object} data subscription data + * @param {string} data.callback subscriber callback url + * @param {*} data.topicId topic id + * @param {number} data.leaseSeconds lease seconds + * @param {string=} data.secret secret + * @param {string=} data.httpRemoteAddr subscriber info + * @param {string=} data.httpFrom subscriber info */ async subscriptionUpsert(dbCtx, data) { this._notImplemented('subscriptionUpsert', arguments); @@ -461,10 +497,10 @@ class Database { /** * Set some subscription fields - * @param {*} dbCtx - * @param {Object} data - * @param {*} data.subscriptionId - * @param {String} data.signatureAlgorithm + * @param {*} dbCtx db context + * @param {object} data subscription data + * @param {*} data.subscriptionId subscription id + * @param {string} data.signatureAlgorithm signature algorithm */ async subscriptionUpdate(dbCtx, data) { this._notImplemented('subscriptionUpdate', arguments); @@ -473,8 +509,8 @@ class Database { /** * Sets the isDeleted flag on a topic, and reset update time. - * @param {*} txCtx - * @param {*} topicId + * @param {*} dbCtx db context + * @param {*} topicId topic id */ async topicDeleted(dbCtx, topicId) { this._notImplemented('topicDeleted', arguments); @@ -483,10 +519,10 @@ class Database { /** * Claim topics to fetch updates for, from available. - * @param {*} dbCtx + * @param {*} dbCtx db context * @param {Integer} wanted maximum topic fetches to claim * @param {Integer} claimTimeoutSeconds age of claimed topics to reclaim - * @param {String} claimant node id claiming these fetches + * @param {string} claimant node id claiming these fetches */ async topicFetchClaim(dbCtx, wanted, claimTimeoutSeconds, claimant) { this._notImplemented('topicFetchClaim', arguments); @@ -495,10 +531,10 @@ class Database { /** * Claim a topic to update. - * @param {*} dbCtx - * @param {*} topicId + * @param {*} dbCtx db context + * @param {*} topicId topic id * @param {Integer} claimTimeoutSeconds age of claimed topics to reclaim - * @param {String} claimant node id claiming these fetches + * @param {string} claimant node id claiming these fetches */ async topicFetchClaimById(dbCtx, topicId, claimTimeoutSeconds, claimant) { this._notImplemented('topicFetchClaim', arguments); @@ -507,8 +543,8 @@ class Database { /** * Reset publish state, and reset deliveries for subscribers. - * @param {*} dbCtx - * @param {*} topicId + * @param {*} dbCtx db context + * @param {*} topicId topic id */ async topicFetchComplete(dbCtx, topicId) { this._notImplemented('topicFetchComplete', arguments); @@ -517,9 +553,9 @@ class Database { /** * Bump count of attempts and release claim on update. - * @param {*} dbCtx - * @param {*} topicId - * @param {Number[]} retryDelays + * @param {*} dbCtx db context + * @param {*} topicId topic id + * @param {number[]} retryDelays retry delays */ async topicFetchIncomplete(dbCtx, topicId, retryDelays) { this._notImplemented('topicFetchIncomplete', arguments); @@ -528,9 +564,8 @@ class Database { /** * Set a topic as ready to be checked for an update. - * @param {*} dbCtx - * @param {*} topicId - * @returns {Boolean} + * @param {*} dbCtx db context + * @param {*} topicId topic id */ async topicFetchRequested(dbCtx, topicId) { this._notImplemented('topicPublish', arguments); @@ -539,7 +574,7 @@ class Database { /** * Get all data for all topics, including subscription count. - * @param {*} dbCtx + * @param {*} dbCtx db context */ async topicGetAll(dbCtx) { this._notImplemented('topicGetAll', arguments); @@ -548,9 +583,9 @@ class Database { /** * Get topic data, without content. - * @param {*} dbCtx - * @param {String} topicUrl - * @param {Boolean} applyDefaults + * @param {*} dbCtx db context + * @param {string} topicUrl topic url + * @param {boolean} applyDefaults merge defaults into result */ async topicGetByUrl(dbCtx, topicUrl, applyDefaults = true) { this._notImplemented('topicGetByUrl', arguments); @@ -559,9 +594,9 @@ class Database { /** * Get topic data, without content. - * @param {*} dbCtx - * @param {*} topicId - * @param {Boolean} applyDefaults + * @param {*} dbCtx db context + * @param {*} topicId topic id + * @param {boolean} applyDefaults merge defaults into result */ async topicGetById(dbCtx, topicId, applyDefaults = true) { this._notImplemented('topicGetById', arguments); @@ -570,10 +605,10 @@ class Database { /** * Returns topic data with content. - * @param {*} dbCx - * @param {*} topicId + * @param {*} dbCtx db context + * @param {*} topicId topic id */ - async topicGetContentById(dbCx, topicId) { + async topicGetContentById(dbCtx, topicId) { this._notImplemented('topicGetContentById', arguments); } @@ -581,7 +616,8 @@ class Database { /** * Attempt to delete a topic, which must be set isDeleted, if there * are no more subscriptions belaying its removal. - * @param {*} topicId + * @param {*} dbCtx db context + * @param {*} topicId topic id */ async topicPendingDelete(dbCtx, topicId) { this._notImplemented('topicPendingDelete', arguments); @@ -590,20 +626,23 @@ class Database { /** * Return an array of the counts of the last #days of topic updates. - * @param {*} dbCtx - * @param {*} topicId - * @param {Number} days - * @returns {Number[]} + * @param {*} dbCtx db context + * @param {*} topicId topic id + * @param {number} days days back to count + * @returns {number[]} updates in last days */ async topicPublishHistory(dbCtx, topicId, days) { this._notImplemented('topicPublishHistory', arguments); } + /** + * @alias {object} TopicData + */ /** * Create or update the basic parameters of a topic. - * @param {*} dbCtx - * @param {TopicData} data + * @param {*} dbCtx db context + * @param {TopicData} data topic data */ async topicSet(dbCtx, data) { this._notImplemented('topicSet', arguments); @@ -612,13 +651,14 @@ class Database { /** * Updates a topic's content data and content update timestamp. - * @param {Object} data - * @param {*} data.topicId - * @param {String} data.content - * @param {String} data.contentHash - * @param {String=} data.contentType - * @param {String=} data.eTag - * @param {String=} data.lastModified + * @param {*} dbCtx db context + * @param {object} data topic data + * @param {*} data.topicId topic id + * @param {string} data.content content + * @param {string} data.contentHash content hash + * @param {string=} data.contentType content-type + * @param {string=} data.eTag etag header + * @param {string=} data.lastModified last modified header */ async topicSetContent(dbCtx, data) { this._notImplemented('topicSetContent', arguments); @@ -627,25 +667,29 @@ class Database { /** * Set some topic fields. - * @param {*} dbCtx - * @param {Object} data - * @param {*} data.topicId - * @param {Number=} data.leaseSecondsPreferred - * @param {Number=} data.leaseSecondsMin - * @param {Number=} data.leaseSecondsMax - * @param {String=} data.publisherValidationUrl - * @param {String=} data.contentHashAlgorithm + * @param {*} dbCtx db context + * @param {object} data topic data + * @param {*} data.topicId topic id + * @param {number=} data.leaseSecondsPreferred preferred topic lease seconds + * @param {number=} data.leaseSecondsMin min lease seconds + * @param {number=} data.leaseSecondsMax max lease seconds + * @param {string=} data.publisherValidationUrl publisher validation url + * @param {string=} data.contentHashAlgorithm content hash algorithm */ async topicUpdate(dbCtx, data) { this._notImplemented('topicUpdate', arguments); } + /** + * @alias {object} Verification + */ /** * Claim pending verifications for attempted resolution. - * @param {*} dbCtx + * @param {*} dbCtx db context * @param {Integer} wanted maximum verifications to claim * @param {Integer} claimTimeoutSeconds age of claimed verifications to reclaim + * @param {*} claimant worker claiming processing * @returns {Verification[]} array of claimed verifications */ async verificationClaim(dbCtx, wanted, claimTimeoutSeconds, claimant) { @@ -655,10 +699,10 @@ class Database { /** * Claim a specific verification by id, if no other similar verification claimed. - * @param {*} dbCtx - * @param {*} verificationId - * @param {Number} claimTimeoutSeconds - * @param {String} claimant + * @param {*} dbCtx db context + * @param {*} verificationId verification id + * @param {number} claimTimeoutSeconds claim duration + * @param {string} claimant worker claiming processing */ async verificationClaimById(dbCtx, verificationId, claimTimeoutSeconds, claimant) { this._notImplemented('verificationClaimById', arguments); @@ -666,12 +710,12 @@ class Database { /** - * Remove the verification, any older - * verifications for that same client/topic, and the claim. - * @param {*} dbCtx - * @param {*} verificationId - * @param {String} callback - * @param {*} topicId + * Remove the verification, any older verifications for that same client/topic, + * and remove the claim. + * @param {*} dbCtx db context + * @param {*} verificationId verification id + * @param {string} callback subscriber callback url + * @param {*} topicId topic id */ async verificationComplete(dbCtx, verificationId, callback, topicId) { this._notImplemented('verificationComplete', arguments); @@ -680,8 +724,8 @@ class Database { /** * Get verification data. - * @param {*} dbCtx - * @param {*} verificationId + * @param {*} dbCtx db context + * @param {*} verificationId verification id */ async verificationGetById(dbCtx, verificationId) { this._notImplemented('verificationGetById', arguments); @@ -691,21 +735,22 @@ class Database { /** * Update database that a client verification was unable to complete. * This releases the delivery claim and reschedules for some future time. - * @param {*} dbCtx - * @param {String} callback client callback url - * @param {*} topicId internal topic id - * @param {Number[]} retryDelays + * @param {*} dbCtx db context + * @param {*} verificationId verification id + * @param {number[]} retryDelays retry delays */ async verificationIncomplete(dbCtx, verificationId, retryDelays) { this._notImplemented('verificationIncomplete', arguments); } + /** + * @alias {object} VerificationData + */ /** * Create a new pending verification. - * @param {*} dbCtx - * @param {VerificationData} data - * @param {Boolean} claim + * @param {*} dbCtx db context + * @param {VerificationData} verification verification data * @returns {*} verificationId */ async verificationInsert(dbCtx, verification) { @@ -715,9 +760,8 @@ class Database { /** * Relinquish the claim on a verification, without any other updates. - * @param {*} dbCtx - * @param {String} callback client callback url - * @param {*} topicId internal topic id + * @param {*} dbCtx db context + * @param {*} verificationId verification id */ async verificationRelease(dbCtx, verificationId) { this._notImplemented('verificationRelease', arguments); @@ -726,12 +770,12 @@ class Database { /** * Updates some fields of an existing (presumably claimed) verification. - * @param {*} dbCtx - * @param {*} verificationId - * @param {Object} data - * @param {String} data.mode - * @param {String} data.reason - * @param {Boolean} data.isPublisherValidated + * @param {*} dbCtx db context + * @param {*} verificationId verification id + * @param {object} data verification data + * @param {string} data.mode mode + * @param {string} data.reason reason + * @param {boolean} data.isPublisherValidated publisher validation result */ async verificationUpdate(dbCtx, verificationId, data) { this._notImplemented('verificationUpdate', arguments); @@ -740,8 +784,8 @@ class Database { /** * Sets the isPublisherValidated flag on a verification and resets the delivery - * @param {*} dbCtx - * @param {*} verificationId + * @param {*} dbCtx db context + * @param {*} verificationId verification id */ async verificationValidated(dbCtx, verificationId) { this._notImplemented('verificationValidated', arguments); diff --git a/src/db/postgres/index.js b/src/db/postgres/index.js index e7a006c..78a4dab 100644 --- a/src/db/postgres/index.js +++ b/src/db/postgres/index.js @@ -29,8 +29,8 @@ const schemaVersionsSupported = { }, max: { major: 1, - minor: 0, - patch: 4, + minor: 1, + patch: 0, }, }; @@ -45,12 +45,13 @@ class DatabasePostgres extends Database { this.noWarnings = options.db.noWarnings; if (options.db.cacheEnabled) { - this.listener = new Listener(logger, this.db, Object.assign({}, options.db.listener, { + this.listener = new Listener(logger, this.db, { + ...options.db.listener, channel: 'topic_changed', dataCallback: this._topicChanged.bind(this), connectionEstablishedCallback: this._listenerEstablished.bind(this), connectionLostCallback: this._listenerLost.bind(this), - })); + }); } // Log queries @@ -58,7 +59,7 @@ class DatabasePostgres extends Database { if (queryLogLevel) { pgpInitOptions.query = (event) => { // Quell outgoing pings - if (event && event.query && event.query.startsWith('NOTIFY')) { + if (event?.query?.startsWith('NOTIFY')) { return; } this.logger[queryLogLevel](_fileScope('pgp:query'), '', { ...common.pick(event || {}, ['query', 'params']) }); @@ -68,6 +69,8 @@ class DatabasePostgres extends Database { // Log errors pgpInitOptions.error = (err, event) => { this.logger.error(_fileScope('pgp:error'), '', { err, event }); + + // TODO: close connection on err.code === '57P03' database shutting down }; // Deophidiate column names in-place, log results @@ -254,7 +257,7 @@ class DatabasePostgres extends Database { /** * Receive notices when topic entry is updated. * Clear relevant cache entry. - * @param {String} payload + * @param {string} payload topic changed event */ _topicChanged(payload) { const _scope = _fileScope('_topicChanged'); @@ -289,11 +292,12 @@ class DatabasePostgres extends Database { /** * Return a cached entry, if available. - * @param {*} key + * @param {*} key key + * @returns {object=} cached data */ _cacheGet(key) { const _scope = _fileScope('_cacheGet'); - if (this.cache && this.cache.has(key)) { + if (this.cache?.has(key)) { const cacheEntry = this.cache.get(key); this.logger.debug(_scope, 'found cache entry', { key, ...common.pick(cacheEntry, ['added', 'hits', 'lastHit']) }); cacheEntry.hits += 1; @@ -305,8 +309,8 @@ class DatabasePostgres extends Database { /** * Store an entry in cache, if available. - * @param {*} key - * @param {*} data + * @param {*} key key + * @param {*} data data */ _cacheSet(key, data) { const _scope = _fileScope('_cacheSet'); @@ -365,17 +369,36 @@ class DatabasePostgres extends Database { } - async authenticationUpsert(dbCtx, identifier, credential) { + async authenticationUpsert(dbCtx, identifier, credential, otpKey) { const _scope = _fileScope('authenticationUpsert'); const scrubbedCredential = '*'.repeat((credential || '').length); - this.logger.debug(_scope, 'called', { identifier, scrubbedCredential }); + const scrubbedOTPKey = '*'.repeat((otpKey || '').length) || null; + this.logger.debug(_scope, 'called', { identifier, scrubbedCredential, scrubbedOTPKey }); let result; try { - result = await dbCtx.result(this.statement.authenticationUpsert, { identifier, credential }); + result = await dbCtx.result(this.statement.authenticationUpsert, { identifier, credential, otpKey }); if (result.rowCount != 1) { throw new DBErrors.UnexpectedResult('did not upsert authentication'); } + } catch (e) { + this.logger.error(_scope, 'failed', { error: e, identifier, scrubbedCredential, scrubbedOTPKey }); + throw e; + } + } + + + async authenticationUpdateCredential(dbCtx, identifier, credential) { + const _scope = _fileScope('authenticationUpdateCredential'); + const scrubbedCredential = '*'.repeat((credential || '').length); + this.logger.debug(_scope, 'called', { identifier, scrubbedCredential }); + + let result; + try { + result = await dbCtx.result(this.statement.authenticationUpdateCredential, { identifier, credential }); + if (result.rowCount != 1) { + throw new DBErrors.UnexpectedResult('did not update authentication credential'); + } } catch (e) { this.logger.error(_scope, 'failed', { error: e, identifier, scrubbedCredential }); throw e; @@ -383,6 +406,24 @@ class DatabasePostgres extends Database { } + async authenticationUpdateOTPKey(dbCtx, identifier, otpKey) { + const _scope = _fileScope('authenticationUpdateOTPKey'); + const scrubbedOTPKey = '*'.repeat((otpKey || '').length) || null; + this.logger.debug(_scope, 'called', { identifier, scrubbedOTPKey }); + + let result; + try { + result = await dbCtx.result(this.statement.authenticationUpdateOtpKey, { identifier, otpKey }); + if (result.rowCount != 1) { + throw new DBErrors.UnexpectedResult('did not update authentication otp key'); + } + } catch (e) { + this.logger.error(_scope, 'failed', { error: e, identifier, scrubbedOTPKey }); + throw e; + } + } + + async subscriptionsByTopicId(dbCtx, topicId) { const _scope = _fileScope('subscriptionsByTopicId'); this.logger.debug(_scope, 'called', { topicId }); diff --git a/src/db/postgres/listener.js b/src/db/postgres/listener.js index 4baf5d0..1ce3b3b 100644 --- a/src/db/postgres/listener.js +++ b/src/db/postgres/listener.js @@ -23,7 +23,10 @@ class PostgresListener { this.logger = logger; this.db = db; - this.options = Object.assign({}, defaultOptions, options); + this.options = { + ...defaultOptions, + ...options, + }; this.notificationEventName = 'notification'; this.connection = null; @@ -83,7 +86,7 @@ class PostgresListener { /** * Notify callback. - * @param {Object} data + * @param {object} data listener notification */ async _onNotification(data) { const _scope = _fileScope('_onNotification'); @@ -98,8 +101,8 @@ class PostgresListener { /** * Notify callback and attempt to reconnect. - * @param {*} error - * @param {*} event + * @param {*} error error + * @param {*} event event */ async _onConnectionLost(error, event) { const _scope = _fileScope('_onConnectionLost'); @@ -122,8 +125,8 @@ class PostgresListener { /** * Schedule an attempt to establish a connection. - * @param {Number} delay - * @param {Number} retriesRemaining + * @param {number} delay reconnect delay + * @param {number} retriesRemaining retry countdown */ async _reconnect(delay, retriesRemaining) { const _scope = _fileScope('_reconnect'); diff --git a/src/db/postgres/sql/authentication-update-credential.sql b/src/db/postgres/sql/authentication-update-credential.sql new file mode 100644 index 0000000..8d48498 --- /dev/null +++ b/src/db/postgres/sql/authentication-update-credential.sql @@ -0,0 +1,3 @@ +UPDATE authentication + SET credential = $(credential) + WHERE identifier = $(identifier) diff --git a/src/db/postgres/sql/authentication-update-otp-key.sql b/src/db/postgres/sql/authentication-update-otp-key.sql new file mode 100644 index 0000000..b639c69 --- /dev/null +++ b/src/db/postgres/sql/authentication-update-otp-key.sql @@ -0,0 +1,3 @@ +UPDATE authentication + SET otp_key = $(otpKey) + WHERE identifier = $(identifier) diff --git a/src/db/postgres/sql/authentication-upsert.sql b/src/db/postgres/sql/authentication-upsert.sql index e86d4fb..f37892f 100644 --- a/src/db/postgres/sql/authentication-upsert.sql +++ b/src/db/postgres/sql/authentication-upsert.sql @@ -1,9 +1,10 @@ -- INSERT INTO authentication - (identifier, credential) + (identifier, credential, otp_key) VALUES - ($(identifier), $(credential)) + ($(identifier), $(credential), $(otpKey)) ON CONFLICT (identifier) DO UPDATE SET identifier = $(identifier), - credential = $(credential) + credential = $(credential), + otp_key = $(otpKey) diff --git a/src/db/postgres/sql/schema/1.1.0/apply.sql b/src/db/postgres/sql/schema/1.1.0/apply.sql new file mode 100644 index 0000000..64be4d4 --- /dev/null +++ b/src/db/postgres/sql/schema/1.1.0/apply.sql @@ -0,0 +1,7 @@ +BEGIN; + + ALTER TABLE authentication ADD COLUMN otp_key TEXT; + + INSERT INTO _meta_schema_version (major, minor, patch) VALUES (1, 1, 0); + +COMMIT; \ No newline at end of file diff --git a/src/db/postgres/sql/schema/1.1.0/er.dot b/src/db/postgres/sql/schema/1.1.0/er.dot new file mode 100644 index 0000000..8dcd3b0 --- /dev/null +++ b/src/db/postgres/sql/schema/1.1.0/er.dot @@ -0,0 +1,140 @@ +digraph WebsubHubERD { + graph[ + rankdir=LR, + overlap=false, + splines=true, + label="Websub Hub Entity-Relations\nPostgres\nSchema 1.1.0", + labelloc="t", + fontsize=26, + ]; + // layout=neato; + node[shape=plain]; + edge[arrowhead=crow]; + + topic [label=< + + + + + + + + + + + + + + + + + + + + + +
TOPIC
id
created
url
lease_seconds_preferred
lease_seconds_min
lease_seconds_max
publisher_validation_url
content_hash_algorithm
is_active
is_deleted
last_publish
content_fetch_next_attempt
content_fetch_attempts_since_success
content_updated
content
content_hash
content_type
http_etag
http_last_modified
+ >]; + + topic_fetch_in_progress [label=< + + + + + + +
TOPIC_FETCH_IN_PROGRESS
id
claimant
claimed
claim_expires
+ >]; + topic:pk_id -> topic_fetch_in_progress:fk_id; + + topic_content_history [label=< + + + + + + +
TOPIC_CONTENT_HISTORY
topic_id
content_updated
content_size
content_hash
+ >]; + topic:pk_id -> topic_content_history:fk_topic_id; + + subscription [label=< + + + + + + + + + + + + + + + + +
SUBSCRIPTION
id
created
topic_id
callback
verified
expires
secret
signature_algorithm
http_remote_addr
http_from
content_delivered
latest_content_delivered
delivery_attempts_since_success
delivery_next_attempt
+ >]; + topic:pk_id -> subscription:fk_topic_id; + + subscription_delivery_in_progress [label=< + + + + + + +
SUBSCRIPTION_DELIVERY_IN_PROGRESS
id
claimant
claimed
claim_expires
+ >]; + subscription:pk_id -> subscription_delivery_in_progress:fk_id; + + verification [label=< + + + + + + + + + + + + + + + + + +
VERIFICATION
id
created
topic_id
callback
secret
signature_algorithm
http_remote_addr
http_from
mode
reason
lease_seconds
is_publisher_validated
request_id
attempts
next_attempt
+ >]; + topic:pk_id -> verification:fk_topic_id; + + verification_in_progress [label=< + + + + + + + + +
VERIFICATION_IN_PROGRESS
id
topic_id
callback
claimant
claimed
claim_expires
+ >]; + verification:pk_id -> verification_in_progress:fk_id; + topic:pk_id -> verification_in_progress:fk_topic_id; + + authentication [label=< + + + + + + + +
AUTHENTICATION
created
last_authenticated
identifier
credential
otp_key
+ >]; + +} diff --git a/src/db/postgres/sql/schema/1.1.0/revert.sql b/src/db/postgres/sql/schema/1.1.0/revert.sql new file mode 100644 index 0000000..fbcc115 --- /dev/null +++ b/src/db/postgres/sql/schema/1.1.0/revert.sql @@ -0,0 +1,5 @@ +BEGIN; + ALTER TABLE authentication DROP COLUMN otp_key; + + DELETE FROM _meta_schema_version WHERE major = 1 AND minor = 1 AND patch = 0; +COMMIT; diff --git a/src/db/schema-version-helper.js b/src/db/schema-version-helper.js index 1f2d374..bc735dc 100644 --- a/src/db/schema-version-helper.js +++ b/src/db/schema-version-helper.js @@ -8,17 +8,17 @@ const path = require('path'); */ /** - * @typedef {Object} SchemaVersionObject - * @property {Number} major - * @property {Number} minor - * @property {Number} patch + * @typedef {object} SchemaVersionObject + * @property {number} major semver major + * @property {number} minor semver minor + * @property {number} patch semver patch */ /** * Split a dotted version string into parts. - * @param {String} v - * @returns {SchemaVersionObject} + * @param {string} v version + * @returns {SchemaVersionObject} version */ function schemaVersionStringToObject(v) { const [ major, minor, patch ] = v.split('.', 3).map((x) => parseInt(x, 10)); @@ -28,8 +28,8 @@ function schemaVersionStringToObject(v) { /** * Render a version object numerically. - * @param {SchemaVersionObject} v - * @returns {Number} + * @param {SchemaVersionObject} v version + * @returns {number} version number */ function schemaVersionObjectToNumber(v) { const vScale = 1000; @@ -39,8 +39,8 @@ function schemaVersionObjectToNumber(v) { /** * Convert dotted version string into number. - * @param {String} v - * @returns {Number} + * @param {string} v version + * @returns {number} version number */ function schemaVersionStringToNumber(v) { return schemaVersionObjectToNumber(schemaVersionStringToObject(v)); @@ -49,9 +49,9 @@ function schemaVersionStringToNumber(v) { /** * Version string comparison, for sorting. - * @param {String} a - * @param {String} b - * @returns {Number} + * @param {string} a version + * @param {string} b version + * @returns {number} difference */ function schemaVersionStringCmp(a, b) { return schemaVersionStringToNumber(a) - schemaVersionStringToNumber(b); @@ -60,9 +60,9 @@ function schemaVersionStringCmp(a, b) { /** * Check if an entry in a directory is a directory containing a migration file. - * @param {String} schemaDir - * @param {String} name - * @returns {Boolean} + * @param {string} schemaDir path to schema version directories + * @param {string} name schema version + * @returns {boolean} is valid schema version */ function isSchemaMigrationDirectory(schemaDir, name) { // eslint-disable-next-line security/detect-non-literal-fs-filename @@ -73,7 +73,7 @@ function isSchemaMigrationDirectory(schemaDir, name) { // eslint-disable-next-line security/detect-non-literal-fs-filename applyStat = fs.statSync(path.join(schemaDir, name, 'apply.sql')); return applyStat.isFile(); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars return false; } } @@ -83,8 +83,8 @@ function isSchemaMigrationDirectory(schemaDir, name) { /** * Return an array of schema migration directory names within engineDir. - * @param {String} engineDir - * @returns {String[]} + * @param {string} engineDir path to engine implementation + * @returns {string[]} schema versions */ function allSchemaVersions(engineDir) { const schemaDir = path.join(engineDir, 'sql', 'schema'); @@ -98,12 +98,12 @@ function allSchemaVersions(engineDir) { /** * Return an array of schema migration directory names within engineDir, * which are within supported range, and are greater than the current - * @param {String} engineDir - * @param {SchemaVersionObject} current - * @param {Object} supported - * @param {SchemaVersionObject} supported.min - * @param {SchemaVersionObject} supported.max - * @returns {String[]} + * @param {string} engineDir path to engine implementation + * @param {SchemaVersionObject} current curernt version + * @param {object} supported supported version range + * @param {SchemaVersionObject} supported.min min version + * @param {SchemaVersionObject} supported.max max version + * @returns {string[]} unapplied versions */ function unappliedSchemaVersions(engineDir, current, supported) { const min = schemaVersionObjectToNumber(supported.min); diff --git a/src/db/sqlite/index.js b/src/db/sqlite/index.js index a30c9b4..6100d49 100644 --- a/src/db/sqlite/index.js +++ b/src/db/sqlite/index.js @@ -19,8 +19,8 @@ const schemaVersionsSupported = { }, max: { major: 1, - minor: 0, - patch: 4, + minor: 1, + patch: 0, }, }; @@ -48,7 +48,7 @@ class DatabaseSQLite extends Database { this.db = new SQLite(dbFilename, sqliteOptions); this.schemaVersionsSupported = schemaVersionsSupported; this.changesSinceLastOptimize = BigInt(0); - this.optimizeAfterChanges = options.db.connectionString.optimizeAfterChanges; + this.optimizeAfterChanges = options.db.optimizeAfterChanges; this.db.pragma('foreign_keys = on'); // Enforce consistency. this.db.pragma('journal_mode = WAL'); // Be faster, expect local filesystem. this.db.defaultSafeIntegers(true); // This probably isn't necessary, but by using these BigInts we keep weird floats out of the query logs. @@ -70,7 +70,7 @@ class DatabaseSQLite extends Database { let metaExists = tableExists.get(); if (metaExists === undefined) { const fPath = path.join(__dirname, 'sql', 'schema', 'init.sql'); - // eslint-disable-next-line security/detect-non-literal-fs-filename + const fSql = fs.readFileSync(fPath, { encoding: 'utf8' }); this.db.exec(fSql); metaExists = tableExists.get(); @@ -131,7 +131,7 @@ class DatabaseSQLite extends Database { }; }; - // eslint-disable-next-line security/detect-non-literal-fs-filename + for (const f of fs.readdirSync(sqlDir)) { const fPath = path.join(sqlDir, f); const { name: fName, ext: fExt } = path.parse(f); @@ -241,7 +241,7 @@ class DatabaseSQLite extends Database { 'verification_in_progress', 'subscription', 'subscription_delivery_in_progress', - ].map((table) => { + ].forEach((table) => { const result = this.db.prepare(`DELETE FROM ${table}`).run(); this.logger.debug(_fileScope('_purgeTables'), 'success', { table, result }); }); @@ -290,17 +290,54 @@ class DatabaseSQLite extends Database { } - authenticationUpsert(dbCtx, identifier, credential) { + authenticationUpsert(dbCtx, identifier, credential, otpKey) { const _scope = _fileScope('authenticationUpsert'); const scrubbedCredential = '*'.repeat((credential || '').length); - this.logger.debug(_scope, 'called', { identifier, scrubbedCredential }); + const scrubbedOTPKey = '*'.repeat((otpKey || '').length) || null; + this.logger.debug(_scope, 'called', { identifier, scrubbedCredential, scrubbedOTPKey }); let result; try { - result = this.statement.authenticationUpsert.run({ identifier, credential }); + result = this.statement.authenticationUpsert.run({ identifier, credential, otpKey }); if (result.changes != 1) { throw new DBErrors.UnexpectedResult('did not upsert authentication'); } + } catch (e) { + this.logger.error(_scope, 'failed', { error: e, identifier, scrubbedCredential, scrubbedOTPKey }); + throw e; + } + } + + + authenticationUpdateOTPKey(dbCtx, identifier, otpKey) { + const _scope = _fileScope('authenticationUpdateOTPKey'); + const scrubbedOTPKey = '*'.repeat((otpKey || '').length) || null; + this.logger.debug(_scope, 'called', { identifier, scrubbedOTPKey }); + + let result; + try { + result = this.statement.authenticationUpdateOtpKey.run({ identifier, otpKey }); + if (result.changes != 1) { + throw new DBErrors.UnexpectedResult('did not update authentication otp key'); + } + } catch (e) { + this.logger.error(_scope, 'failed', { error: e, identifier, scrubbedOTPKey }); + throw e; + } + } + + + authenticationUpdateCredential(dbCtx, identifier, credential) { + const _scope = _fileScope('authenticationUpdateCredential'); + const scrubbedCredential = '*'.repeat((credential || '').length); + this.logger.debug(_scope, 'called', { identifier, scrubbedCredential }); + + let result; + try { + result = this.statement.authenticationUpdateCredential.run({ identifier, credential }); + if (result.changes != 1) { + throw new DBErrors.UnexpectedResult('did not update authentication credential'); + } } catch (e) { this.logger.error(_scope, 'failed', { error: e, identifier, scrubbedCredential }); throw e; @@ -310,7 +347,8 @@ class DatabaseSQLite extends Database { /** * Converts engine subscription fields to native types. - * @param {Object} data + * @param {object} data subscription data + * @returns {object} data */ static _subscriptionDataToNative(data) { if (data) { @@ -704,7 +742,8 @@ class DatabaseSQLite extends Database { /** * Converts engine topic fields to native types. - * @param {Object} data + * @param {object} data topic + * @returns {object} topic data */ static _topicDataToNative(data) { if (data) { @@ -992,7 +1031,7 @@ class DatabaseSQLite extends Database { /** * Converts engine verification fields to native types. - * @param {Object} data + * @param {object} data verification */ static _verificationDataToNative(data) { if (data) { @@ -1046,6 +1085,7 @@ class DatabaseSQLite extends Database { /** * Convert native verification fields to engine types. + * @param {object} data verification */ static _verificationDataToEngine(data) { if (data) { @@ -1146,4 +1186,4 @@ class DatabaseSQLite extends Database { } -module.exports = DatabaseSQLite; \ No newline at end of file +module.exports = DatabaseSQLite; diff --git a/src/db/sqlite/sql/authentication-update-credential.sql b/src/db/sqlite/sql/authentication-update-credential.sql new file mode 100644 index 0000000..021b9ec --- /dev/null +++ b/src/db/sqlite/sql/authentication-update-credential.sql @@ -0,0 +1,3 @@ +UPDATE authentication + SET credential = :credential + WHERE identifier = :identifier diff --git a/src/db/sqlite/sql/authentication-update-otp-key.sql b/src/db/sqlite/sql/authentication-update-otp-key.sql new file mode 100644 index 0000000..d52506b --- /dev/null +++ b/src/db/sqlite/sql/authentication-update-otp-key.sql @@ -0,0 +1,3 @@ +UPDATE authentication + SET otp_key = :otpKey + WHERE identifier = :identifier diff --git a/src/db/sqlite/sql/authentication-upsert.sql b/src/db/sqlite/sql/authentication-upsert.sql index 8a141ee..b830719 100644 --- a/src/db/sqlite/sql/authentication-upsert.sql +++ b/src/db/sqlite/sql/authentication-upsert.sql @@ -1,9 +1,10 @@ -- INSERT INTO authentication - (identifier, credential) + (identifier, credential, otp_key) VALUES - (:identifier, :credential) + (:identifier, :credential, :otpKey) ON CONFLICT (identifier) DO UPDATE SET identifier = :identifier, - credential = :credential + credential = :credential, + otp_key = :otpKey diff --git a/src/db/sqlite/sql/schema/1.1.0/apply.sql b/src/db/sqlite/sql/schema/1.1.0/apply.sql new file mode 100644 index 0000000..fdfd499 --- /dev/null +++ b/src/db/sqlite/sql/schema/1.1.0/apply.sql @@ -0,0 +1,7 @@ +BEGIN; + + ALTER TABLE authentication ADD COLUMN otp_key TEXT CHECK (typeof(otp_key) IN ('text', 'null')); + + INSERT INTO _meta_schema_version (major, minor, patch) VALUES (1, 1, 0); + +COMMIT; diff --git a/src/db/sqlite/sql/schema/1.1.0/er.dot b/src/db/sqlite/sql/schema/1.1.0/er.dot new file mode 100644 index 0000000..0436d73 --- /dev/null +++ b/src/db/sqlite/sql/schema/1.1.0/er.dot @@ -0,0 +1,140 @@ +digraph WebsubHubERD { + graph[ + rankdir=LR, + overlap=false, + splines=true, + label="Websub Hub Entity-Relations\nSQLite\nSchema 1.1.0", + labelloc="t", + fontsize=26, + ]; + // layout=neato; + node[shape=plain]; + edge[arrowhead=crow]; + + topic [label=< + + + + + + + + + + + + + + + + + + + + + +
TOPIC
id
created
url
lease_seconds_preferred
lease_seconds_min
lease_seconds_max
publisher_validation_url
content_hash_algorithm
is_active
is_deleted
last_publish
content_fetch_next_attempt
content_fetch_attempts_since_success
content_updated
content
content_hash
content_type
http_etag
http_last_modified
+ >]; + + topic_fetch_in_progress [label=< + + + + + + +
TOPIC_FETCH_IN_PROGRESS
id
claimant
claimed
claim_expires
+ >]; + topic:pk_id -> topic_fetch_in_progress:fk_id; + + topic_content_history [label=< + + + + + + +
TOPIC_CONTENT_HISTORY
topic_id
content_updated
content_size
content_hash
+ >]; + topic:pk_id -> topic_content_history:fk_topic_id; + + subscription [label=< + + + + + + + + + + + + + + + + +
SUBSCRIPTION
id
created
topic_id
callback
verified
expires
secret
signature_algorithm
http_remote_addr
http_from
content_delivered
latest_content_delivered
delivery_attempts_since_success
delivery_next_attempt
+ >]; + topic:pk_id -> subscription:fk_topic_id; + + subscription_delivery_in_progress [label=< + + + + + + +
SUBSCRIPTION_DELIVERY_IN_PROGRESS
id
claimant
claimed
claim_expires
+ >]; + subscription:pk_id -> subscription_delivery_in_progress:fk_id; + + verification [label=< + + + + + + + + + + + + + + + + + +
VERIFICATION
id
created
topic_id
callback
secret
signature_algorithm
http_remote_addr
http_from
mode
reason
lease_seconds
is_publisher_validated
request_id
attempts
next_attempt
+ >]; + topic:pk_id -> verification:fk_topic_id; + + verification_in_progress [label=< + + + + + + + + +
VERIFICATION_IN_PROGRESS
id
topic_id
callback
claimant
claimed
claim_expires
+ >]; + verification:pk_id -> verification_in_progress:fk_id; + topic:pk_id -> verification_in_progress:fk_topic_id; + + authentication [label=< + + + + + + + +
AUTHENTICATION
created
last_authenticated
identifier
credential
otp_key
+ >]; + +} diff --git a/src/db/sqlite/sql/schema/1.1.0/revert.sql b/src/db/sqlite/sql/schema/1.1.0/revert.sql new file mode 100644 index 0000000..fbcc115 --- /dev/null +++ b/src/db/sqlite/sql/schema/1.1.0/revert.sql @@ -0,0 +1,5 @@ +BEGIN; + ALTER TABLE authentication DROP COLUMN otp_key; + + DELETE FROM _meta_schema_version WHERE major = 1 AND minor = 1 AND patch = 0; +COMMIT; diff --git a/src/link-helper.js b/src/link-helper.js index 93a947b..f35aca9 100644 --- a/src/link-helper.js +++ b/src/link-helper.js @@ -15,6 +15,12 @@ const { Iconv } = require('iconv'); const _fileScope = common.fileScope(__filename); +/** + * Helper for accessing headers + * @param {object} headers header object + * @param {string} header header name + * @returns {string} header content + */ function getHeader(headers, header) { return headers[header.toLowerCase()]; } @@ -30,10 +36,10 @@ class LinkHelper { /** * Determine if this hub is listed in response data from url. - * @param {String} url - * @param {Object} headers - * @param {String|Buffer} body - * @returns {Boolean} + * @param {string} url content url + * @param {object} headers headers from accessing url + * @param {string | Buffer} body body from accessing url + * @returns {Promise} url lists this hub */ async validHub(url, headers, body) { const _scope = _fileScope('validHub'); @@ -97,15 +103,18 @@ class LinkHelper { } + /** + * @typedef {object} ContentType + * @property {string} mediaType media type + * @property {object} params map of parameters + */ /** * Convert a Content-Type string to normalized components. * RFC7231 §3.1.1 * N.B. this non-parser implementation will not work if a parameter * value for some reason includes a ; or = within a quoted-string. - * @param {String} contentTypeHeader - * @returns {Object} contentType - * @returns {String} contentType.mediaType - * @returns {Object} contentType.params + * @param {string} contentTypeHeader content type header + * @returns {ContentType} contentType */ static parseContentType(contentTypeHeader) { const [ mediaType, ...params ] = (contentTypeHeader || '').split(/ *; */); @@ -113,7 +122,7 @@ class LinkHelper { mediaType: mediaType.toLowerCase() || Enum.ContentType.ApplicationOctetStream, params: params.reduce((obj, param) => { const [field, value] = param.split('='); - const isQuoted = value.charAt(0) === '"' && value.charAt(value.length - 1) === '"'; + const isQuoted = value.startsWith('"') && value.endsWith('"'); obj[field.toLowerCase()] = isQuoted ? value.slice(1, value.length - 1) : value; return obj; }, {}), @@ -123,9 +132,9 @@ class LinkHelper { /** * Parse XML-ish feed content, extracting link elements into our own format. - * @param {String} feedurl - * @param {String} body - * @returns {Object[]} + * @param {string} feedurl feed url + * @param {string} body feed body + * @returns {Promise} array of link elements */ async linksFromFeedBody(feedurl, body) { const _scope = _fileScope('linksFromFeedBody'); @@ -179,7 +188,8 @@ class LinkHelper { /** * Parse HTML-ish content, extracting link elements into our own format. - * @param {String} body + * @param {string} body html body + * @returns {object[]} array of link elements */ linksFromHTMLBody(body) { const _scope = _fileScope('linksFromHTMLBody'); @@ -207,18 +217,18 @@ class LinkHelper { /** * Attempt to resolve a relative target URI - * @param {String} uri - * @param {String} context - * @returns {String} + * @param {string} uri target + * @param {string} context base + * @returns {string} uri */ absoluteURI(uri, context) { const _scope = _fileScope('absoluteURI'); try { new URL(uri); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars try { uri = new URL(uri, context).href; - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.debug(_scope, 'could not resolve link URI', { uri, context }); } } @@ -228,8 +238,8 @@ class LinkHelper { /** * Return all link targets with a hub relation. - * @param {Object[]} links - * @returns {String[]} + * @param {object[]} links array of link objects + * @returns {string[]} array of hub targets */ static locateHubTargets(links) { return links diff --git a/src/logger/data-sanitizers.js b/src/logger/data-sanitizers.js index a6b444b..0bb261c 100644 --- a/src/logger/data-sanitizers.js +++ b/src/logger/data-sanitizers.js @@ -2,14 +2,14 @@ /** * Scrub credential from POST login body data. - * @param {Object} data - * @param {Boolean} sanitize - * @returns {Boolean} + * @param {object} data data + * @param {boolean} sanitize perform sanitization + * @returns {boolean} needed sanitization */ function sanitizePostCredential(data, sanitize = true) { let unclean = false; - const credentialLength = data && data.ctx && data.ctx.parsedBody && data.ctx.parsedBody.credential && data.ctx.parsedBody.credential.length; + const credentialLength = data?.ctx?.parsedBody?.credential?.length; if (credentialLength) { unclean = true; } diff --git a/src/manager.js b/src/manager.js index 74730c2..a7f9f55 100644 --- a/src/manager.js +++ b/src/manager.js @@ -27,11 +27,14 @@ class Manager { this.communication = new Communication(logger, db, options); } + /** + * @typedef {import('node:http')} http + */ /** * GET request for healthcheck. - * @param {http.ServerResponse} res - * @param {object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getHealthcheck(res, ctx) { const _scope = _fileScope('getHealthcheck'); @@ -46,9 +49,9 @@ class Manager { /** * GET request for root. - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getRoot(req, res, ctx) { const _scope = _fileScope('getRoot'); @@ -60,25 +63,26 @@ class Manager { } - /** All the fields the root handler deals with. + /** + * All the fields the root handler deals with. * @typedef {object} RootData - * @property {string} callback - url - * @property {string} mode - * @property {string} topic - * @property {number} topicId - * @property {string} leaseSeconds - * @property {string} secret - * @property {string} httpRemoteAddr - * @property {string} httpFrom - * @property {boolean} isSecure - * @property {boolean} isPublisherValidated + * @property {string} callback url + * @property {string} mode mode + * @property {string} topic topic + * @property {number} topicId topic id + * @property {string} leaseSeconds lease seconds + * @property {string} secret secret + * @property {string} httpRemoteAddr remote address + * @property {string} httpFrom from + * @property {boolean} isSecure is secure + * @property {boolean} isPublisherValidated is published validated */ /** * Extract api parameters. - * @param {http.ClientRequest} req - * @param {Object} ctx - * @returns {RootData} + * @param {http.ClientRequest} req request + * @param {object} ctx context + * @returns {RootData} root data */ static _getRootData(req, ctx) { const postData = ctx.parsedBody; @@ -100,11 +104,12 @@ class Manager { /** * - * @param {*} dbCtx - * @param {RootData} data - * @param {String[]} warn - * @param {String[]} err - * @param {String} requestId + * @param {*} dbCtx db context + * @param {RootData} data root data + * @param {string[]} warn warnings + * @param {string[]} err errors + * @param {string} requestId request id + * @returns {Promise} */ async _validateRootData(dbCtx, data, warn, err, requestId) { // These checks can modify data, so order matters. @@ -118,10 +123,12 @@ class Manager { * Check that requested topic exists and values are in range. * Sets topic id, publisher validation state, and requested lease * seconds on data. - * @param {*} dbCtx - * @param {RootData} data - * @param {String[]} warn - * @param {String[]} err + * @param {*} dbCtx db context + * @param {RootData} data root data + * @param {string[]} warn warnings + * @param {string[]} err errors + * @param {string} requestId request id + * @returns {Promise} */ async _checkTopic(dbCtx, data, warn, err, requestId) { const _scope = _fileScope('_checkTopic'); @@ -135,7 +142,7 @@ class Manager { try { new URL(data.topic); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars err.push('invalid topic url (failed to parse url)'); return; } @@ -156,14 +163,12 @@ class Manager { if (data.leaseSeconds === undefined || isNaN(data.leaseSeconds)) { data.leaseSeconds = topic.leaseSecondsPreferred; - } else { - if (data.leaseSeconds > topic.leaseSecondsMax) { - data.leaseSeconds = topic.leaseSecondsMax; - warn.push(`requested lease too long, using ${data.leaseSeconds}`); - } else if (data.leaseSeconds < topic.leaseSecondsMin) { - data.leaseSeconds = topic.leaseSecondsMin; - warn.push(`requested lease too short, using ${data.leaseSeconds}`); - } + } else if (data.leaseSeconds > topic.leaseSecondsMax) { + data.leaseSeconds = topic.leaseSecondsMax; + warn.push(`requested lease too long, using ${data.leaseSeconds}`); + } else if (data.leaseSeconds < topic.leaseSecondsMin) { + data.leaseSeconds = topic.leaseSecondsMin; + warn.push(`requested lease too short, using ${data.leaseSeconds}`); } if (topic.publisherValidationUrl) { @@ -174,9 +179,9 @@ class Manager { /** * Check data for valid callback url and scheme constraints. - * @param {RootData} data - * @param {String[]} warn - * @param {String[]} err + * @param {RootData} data root data + * @param {string[]} warn warnings + * @param {string[]} err errors */ _checkCallbackAndSecrets(data, warn, err) { let isCallbackSecure = false; @@ -187,7 +192,7 @@ class Manager { try { const c = new URL(data.callback); isCallbackSecure = (c.protocol.toLowerCase() === 'https:'); // Colon included because url module is weird - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars err.push('invalid callback url (failed to parse url'); return; } @@ -214,11 +219,11 @@ class Manager { /** * Check mode validity and subscription requirements. * Publish mode is handled elsewhere in the flow. - * @param {*} dbCtx - * @param {RootData} data - * @param {String[]} warn - * @param {String[]} err - * @param {String} requestId + * @param {*} dbCtx db context + * @param {RootData} data root data + * @param {string[]} warn warnings + * @param {string[]} err errors + * @returns {Promise} */ async _checkMode(dbCtx, data, warn, err) { switch (data.mode) { @@ -233,11 +238,10 @@ class Manager { } if (s === undefined) { err.push('not subscribed'); - } else { - if (s.expires < currentEpoch) { - err.push('subscription already expired'); - } + } else if (s.expires < currentEpoch) { + err.push('subscription already expired'); } + break; } @@ -251,7 +255,7 @@ class Manager { /** * Determine if a topic url is allowed to be created. * In the future, this may be more complicated. - * @returns {Boolean} + * @returns {boolean} is public hub */ _newTopicCreationAllowed() { return this.options.manager.publicHub; @@ -262,11 +266,10 @@ class Manager { * Check that a publish request's topic(s) are valid and exist, * returning an array with the results for each. * For a public-hub publish request, creates topics if they do not exist. - * @param {*} dbCtx - * @param {RootData} data - * @param {String[]} warn - * @param {String[]} err - * @param {String} requestId + * @param {*} dbCtx db context + * @param {RootData} data root data + * @param {string} requestId request id + * @returns {Promise} results */ async _publishTopics(dbCtx, data, requestId) { const _scope = _fileScope('_checkPublish'); @@ -289,7 +292,7 @@ class Manager { if (!topic && this._newTopicCreationAllowed()) { try { new URL(url); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars result.err.push('invalid topic url (failed to parse url)'); return result; } @@ -312,7 +315,9 @@ class Manager { /** * Render response for multi-topic publish requests. - * @param {Object[]} publishTopics + * @param {object} ctx context + * @param {object[]} publishTopics topics + * @returns {string} response content */ static multiPublishContent(ctx, publishTopics) { const responses = publishTopics.map((topic) => ({ @@ -341,10 +346,10 @@ class Manager { /** * Process a publish request. - * @param {*} dbCtx - * @param {Object} data - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {*} dbCtx db context + * @param {object} data data + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async _publishRequest(dbCtx, data, res, ctx) { const _scope = _fileScope('_parsePublish'); @@ -354,7 +359,7 @@ class Manager { // Parse and validate all the topics in the request. data.publishTopics = await this._publishTopics(dbCtx, data, requestId); - if (!data.publishTopics || !data.publishTopics.length) { + if (!data?.publishTopics?.length) { const details = Manager._prettyDetails(['no valid topic urls to publish'], []); throw new ResponseError(Enum.ErrorResponse.BadRequest, details); } @@ -389,7 +394,7 @@ class Manager { && validPublishTopics.length) { try { await Promise.all(validPublishTopics.map(async (topicResult) => this.communication.topicFetchClaimAndProcessById(dbCtx, topicResult.topicId, requestId))); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.error(_scope, 'topicFetchClaimAndProcessById failed', { data, validPublishTopics, requestId }); // Don't bother re-throwing, as we've already ended this response. } @@ -399,9 +404,9 @@ class Manager { /** * Annotate any encountered issues. - * @param {String[]} err - * @param {String[]} warn - * @returns {String[]} + * @param {string[]} err errors + * @param {string[]} warn warnings + * @returns {string[]} rendered list of errors and warnings */ static _prettyDetails(err, warn) { return [ @@ -413,9 +418,9 @@ class Manager { /** * POST request for root. - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async postRoot(req, res, ctx) { const _scope = _fileScope('postRoot'); @@ -463,7 +468,7 @@ class Manager { && id) { try { await this.communication.verificationClaimAndProcessById(dbCtx, id, requestId); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.error(_scope, 'verificationClaimAndProcessById failed', { ...data, id, requestId }); // Don't bother re-throwing, as we've already ended this response. } @@ -474,15 +479,15 @@ class Manager { /** * Render topic info content. - * @param {Object} ctx - * @param {String} ctx.responseType - * @param {String} ctx.topicUrl - * @param {Number} ctx.count - * @returns {String} + * @param {object} ctx context + * @param {string} ctx.responseType response type + * @param {string} ctx.topicUrl topic url + * @param {number} ctx.count count of subscribers + * @returns {string} response content */ // eslint-disable-next-line class-methods-use-this infoContent(ctx) { - // eslint-disable-next-line sonarjs/no-small-switch + switch (ctx.responseType) { case Enum.ContentType.ApplicationJson: return JSON.stringify({ @@ -501,8 +506,8 @@ class Manager { /** * GET request for /info?topic=url&format=type - * @param {http.ServerResponse} res - * @param {object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getInfo(res, ctx) { const _scope = _fileScope('getInfo'); @@ -530,7 +535,7 @@ class Manager { try { new URL(ctx.topicUrl); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars throw new ResponseError(Enum.ErrorResponse.BadRequest, 'invalid topic'); } @@ -553,9 +558,9 @@ class Manager { /** * label the bars of the topic update history graph - * @param {Number} index - * @param {Number} value - * @returns {String} + * @param {number} index index + * @param {number} value value + * @returns {string} caption */ static _historyBarCaption(index, value) { let when; @@ -569,14 +574,14 @@ class Manager { default: when = `${index} days ago`; } - return `${when}, ${value ? value : 'no'} update${value === 1 ? '': 's'}`; + return `${when}, ${value || 'no'} update${value === 1 ? '': 's'}`; } /** * GET SVG chart of topic update history - * @param {http.ServerResponse} res - * @param {object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getHistorySVG(res, ctx) { const _scope = _fileScope('getHistorySVG'); @@ -610,9 +615,9 @@ class Manager { /** * Determine if a profile url matches enough of a topic url to describe control over it. * Topic must match hostname and start with the profile's path. - * @param {URL} profileUrlObj - * @param {URL} topicUrlObj - * @returns {Boolean} + * @param {URL} profileUrlObj profile url + * @param {URL} topicUrlObj topic url + * @returns {boolean} profile is super-url of topic */ static _profileControlsTopic(profileUrlObj, topicUrlObj) { const hostnameMatches = profileUrlObj.hostname === topicUrlObj.hostname; @@ -623,8 +628,8 @@ class Manager { /** * GET request for authorized /admin information. - * @param {http.ServerResponse} res - * @param {object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getAdminOverview(res, ctx) { const _scope = _fileScope('getAdminOverview'); @@ -636,7 +641,7 @@ class Manager { this.logger.debug(_scope, 'got topics', { topics: ctx.topics }); // Profile users can only see related topics. - if (ctx.session && ctx.session.authenticatedProfile) { + if (ctx?.session?.authenticatedProfile) { const profileUrlObj = new URL(ctx.session.authenticatedProfile); ctx.topics = ctx.topics.filter((topic) => { const topicUrlObj = new URL(topic.url); @@ -651,8 +656,8 @@ class Manager { /** * GET request for authorized /admin/topic/:topicId information. - * @param {http.ServerResponse} res - * @param {object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getTopicDetails(res, ctx) { const _scope = _fileScope('getTopicDetails'); @@ -673,7 +678,7 @@ class Manager { this.logger.debug(_scope, 'got topic details', { topic: ctx.topic, subscriptions: ctx.subscriptions, updates: ctx.publishCount }); // Profile users can only see related topics. - if (ctx.session && ctx.session.authenticatedProfile) { + if (ctx?.session?.authenticatedProfile) { const profileUrlObj = new URL(ctx.session.authenticatedProfile); const topicUrlObj = new URL(ctx.topic.url); if (!Manager._profileControlsTopic(profileUrlObj, topicUrlObj)) { @@ -683,14 +688,14 @@ class Manager { } res.end(Template.adminTopicDetailsHTML(ctx, this.options)); - this.logger.info(_scope, 'finished', { ctx, subscriptions: ctx.subscriptions.length, topic: ctx.topic && ctx.topic.id || ctx.topic }); + this.logger.info(_scope, 'finished', { ctx, subscriptions: ctx.subscriptions.length, topic: ctx?.topic?.id || ctx.topic }); } /** * PATCH and DELETE for updating topic data. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async updateTopic(res, ctx) { const _scope = _fileScope('updateTopic'); @@ -773,8 +778,8 @@ class Manager { /** * PATCH and DELETE for updating subscription data. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async updateSubscription(res, ctx) { const _scope = _fileScope('updateSubscription'); @@ -853,8 +858,8 @@ class Manager { /** * POST request for manually running worker. - * @param {http.ServerResponse} res - * @param {object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async processTasks(res, ctx) { const _scope = _fileScope('processTasks'); diff --git a/src/service.js b/src/service.js index e769599..fbbb1c4 100644 --- a/src/service.js +++ b/src/service.js @@ -10,17 +10,18 @@ const common = require('./common'); const Enum = require('./enum'); const Manager = require('./manager'); const { Authenticator, SessionManager } = require('@squeep/authentication-module'); +const { initContext, navLinks } = require('./template/template-helper'); const path = require('path'); const _fileScope = common.fileScope(__filename); class Service extends Dingus { - constructor(logger, db, options) { + constructor(logger, db, options, asyncLocalStorage) { super(logger, { ...options.dingus, ignoreTrailingSlash: false, }); - + this.asyncLocalStorage = asyncLocalStorage; this.manager = new Manager(logger, db, options); this.authenticator = new Authenticator(logger, db, options); this.sessionManager = new SessionManager(logger, this.authenticator, options); @@ -31,10 +32,10 @@ class Service extends Dingus { this.on('POST', '/', this.handlerPostRoot.bind(this)); // Information page about service - this.on(['GET', 'HEAD'], '/', this.handlerGetRoot.bind(this)); + this.on(['GET'], '/', this.handlerGetRoot.bind(this)); // Give load-balancers something to check - this.on(['GET', 'HEAD'], '/healthcheck', this.handlerGetHealthcheck.bind(this)); + this.on(['GET'], '/healthcheck', this.handlerGetHealthcheck.bind(this)); // Public information about topics this.on('GET', '/info', this.handlerGetInfo.bind(this)); @@ -42,17 +43,17 @@ class Service extends Dingus { // These routes are intended for accessing static content during development. // In production, a proxy server would likely handle these first. - this.on(['GET', 'HEAD'], '/static', this.handlerRedirect.bind(this), `${options.dingus.proxyPrefix}/static/`); - this.on(['GET', 'HEAD'], '/static/', this.handlerGetStaticFile.bind(this), 'index.html'); - this.on(['GET', 'HEAD'], '/static/:file', this.handlerGetStaticFile.bind(this)); - this.on(['GET', 'HEAD'], '/favicon.ico', this.handlerGetStaticFile.bind(this), 'favicon.ico'); - this.on(['GET', 'HEAD'], '/robots.txt', this.handlerGetStaticFile.bind(this), 'robots.txt'); + this.on(['GET'], '/static', this.handlerRedirect.bind(this), `${options.dingus.proxyPrefix}/static/`); + this.on(['GET'], '/static/', this.handlerGetStaticFile.bind(this), 'index.html'); + this.on(['GET'], '/static/:file', this.handlerGetStaticFile.bind(this)); + this.on(['GET'], '/favicon.ico', this.handlerGetStaticFile.bind(this), 'favicon.ico'); + this.on(['GET'], '/robots.txt', this.handlerGetStaticFile.bind(this), 'robots.txt'); // Private informational endpoints - this.on(['GET', 'HEAD'], '/admin', this.handlerRedirect.bind(this), `${options.dingus.proxyPrefix}/admin/`); - this.on(['GET', 'HEAD'], '/admin/', this.handlerGetAdminOverview.bind(this)); - this.on(['GET', 'HEAD'], '/admin/topic/:topicId', this.handlerGetAdminTopicDetails.bind(this)); - this.on(['GET', 'HEAD'], '/admin/topic/:topicId/history.svg', this.handlerGetHistorySVG.bind(this)); + this.on(['GET'], '/admin', this.handlerRedirect.bind(this), `${options.dingus.proxyPrefix}/admin/`); + this.on(['GET'], '/admin/', this.handlerGetAdminOverview.bind(this)); + this.on(['GET'], '/admin/topic/:topicId', this.handlerGetAdminTopicDetails.bind(this)); + this.on(['GET'], '/admin/topic/:topicId/history.svg', this.handlerGetHistorySVG.bind(this)); // Private data-editing endpoints this.on(['PATCH', 'DELETE'], '/admin/topic/:topicId', this.handlerUpdateTopic.bind(this)); @@ -62,23 +63,52 @@ class Service extends Dingus { this.on('POST', '/admin/process', this.handlerPostAdminProcess.bind(this)); // Admin login - this.on(['GET', 'HEAD'], '/admin/login', this.handlerGetAdminLogin.bind(this)); + this.on(['GET'], '/admin/login', this.handlerGetAdminLogin.bind(this)); this.on(['POST'], '/admin/login', this.handlerPostAdminLogin.bind(this)); this.on(['GET'], '/admin/logout', this.handlerGetAdminLogout.bind(this)); this.on(['GET'], '/admin/_ia', this.handlerGetAdminIA.bind(this)); + this.on(['GET'], '/admin/settings', this.handlerGetAdminSettings.bind(this)); + this.on(['POST'], '/admin/settings', this.handlerPostAdminSettings.bind(this)); + + } + + /** + * @typedef {import('node:http')} http + */ + /** + * Rearrange logging data. + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context + */ + async preHandler(req, res, ctx) { + await super.preHandler(req, res, ctx); + ctx.url = req.url; // Persisted for logout redirect + + const logObject = this.asyncLocalStorage.getStore(); + // FIXME: for some reason, returning from the super.preHandler sometimes loses async context? + // Workaround until cause and solution are found. + if (logObject) { + logObject.requestId = ctx.requestId; + delete ctx.requestId; + } else { + this.logger.debug(_fileScope('preHandler'), 'lost async context', { req, ctx }); + } } /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostRoot(req, res, ctx) { const _scope = _fileScope('handlerPostRoot'); this.logger.debug(_scope, 'called', { req, ctx }); + initContext(ctx); + this.setResponseType(this.responseTypes, req, res, ctx); await this.ingestBody(req, res, ctx); @@ -87,9 +117,9 @@ class Service extends Dingus { /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetRoot(req, res, ctx) { const _scope = _fileScope('handlerGetRoot'); @@ -98,7 +128,7 @@ class Service extends Dingus { ]; this.logger.debug(_scope, 'called', { req, ctx }); - Dingus.setHeadHandler(req, res, ctx); + initContext(ctx); this.setResponseType(responseTypes, req, res, ctx); @@ -109,15 +139,13 @@ class Service extends Dingus { /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetHealthcheck(req, res, ctx) { const _scope = _fileScope('handlerGetHealthcheck'); this.logger.debug(_scope, 'called', { req, ctx }); - - Dingus.setHeadHandler(req, res, ctx); this.setResponseType(this.responseTypes, req, res, ctx); @@ -126,9 +154,9 @@ class Service extends Dingus { /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetInfo(req, res, ctx) { const _scope = _fileScope('handlerGetInfo'); @@ -136,8 +164,6 @@ class Service extends Dingus { const responseTypes = [...this.responseTypes, Enum.ContentType.ImageSVG]; - Dingus.setHeadHandler(req, res, ctx); - this.setResponseType(responseTypes, req, res, ctx); await this.manager.getInfo(res, ctx); @@ -150,8 +176,6 @@ class Service extends Dingus { const responseTypes = [Enum.ContentType.ImageSVG]; - Dingus.setHeadHandler(req, res, ctx); - this.setResponseType(responseTypes, req, res, ctx); await this.manager.getHistorySVG(res, ctx); @@ -159,15 +183,15 @@ class Service extends Dingus { /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminOverview(req, res, ctx) { const _scope = _fileScope('handlerGetAdminOverview'); this.logger.debug(_scope, 'called', { req, ctx }); - Dingus.setHeadHandler(req, res, ctx); + initContext(ctx); this.setResponseType(this.responseTypes, req, res, ctx); @@ -178,15 +202,15 @@ class Service extends Dingus { /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminTopicDetails(req, res, ctx) { const _scope = _fileScope('handlerGetAdminTopicDetails'); this.logger.debug(_scope, 'called', { req, ctx }); - Dingus.setHeadHandler(req, res, ctx); + initContext(ctx); this.setResponseType(this.responseTypes, req, res, ctx); @@ -198,9 +222,10 @@ class Service extends Dingus { /** * If no body was sent, do not parse (and thus avoid possible unsupported media type error). - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context + * @returns {Promise} parsed body */ async maybeIngestBody(req, res, ctx) { return super.ingestBody(req, res, ctx, { @@ -210,9 +235,9 @@ class Service extends Dingus { /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerUpdateTopic(req, res, ctx) { const _scope = _fileScope('handlerUpdateTopic'); @@ -229,9 +254,9 @@ class Service extends Dingus { /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerUpdateSubscription(req, res, ctx) { const _scope = _fileScope('handlerUpdateSubscription'); @@ -245,12 +270,12 @@ class Service extends Dingus { ctx.method = req.method; await this.manager.updateSubscription(res, ctx); } - + /** - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostAdminProcess(req, res, ctx) { const _scope = _fileScope('handlerPostAdminProcess'); @@ -266,15 +291,15 @@ class Service extends Dingus { /** * Delegate login to authentication module. - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminLogin(req, res, ctx) { const _scope = _fileScope('handlerGetAdminLogin'); this.logger.debug(_scope, 'called', { req, ctx }); - Dingus.setHeadHandler(req, res, ctx); + initContext(ctx); this.setResponseType(this.responseTypes, req, res, ctx); @@ -284,14 +309,16 @@ class Service extends Dingus { /** * Delegate login to authentication module. - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostAdminLogin(req, res, ctx) { const _scope = _fileScope('handlerPostAdminLogin'); this.logger.debug(_scope, 'called', { req, ctx }); + initContext(ctx); + this.setResponseType(this.responseTypes, req, res, ctx); await this.authenticator.sessionOptionalLocal(req, res, ctx); @@ -302,16 +329,59 @@ class Service extends Dingus { } + /** + * Delegate account settings to authentication module. + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context + */ + async handlerGetAdminSettings(req, res, ctx) { + const _scope = _fileScope('handlerGetAdminSettings'); + this.logger.debug(_scope, 'called', { req, ctx }); + + initContext(ctx); + + this.setResponseType(this.responseTypes, req, res, ctx); + + if (await this.authenticator.sessionRequiredLocal(req, res, ctx)) { + await this.sessionManager.getAdminSettings(res, ctx, navLinks); + } + } + + + /** + * Delegate account settings to authentication module. + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context + */ + async handlerPostAdminSettings(req, res, ctx) { + const _scope = _fileScope('handlerPostAdminSettings'); + this.logger.debug(_scope, 'called', { req, ctx }); + + initContext(ctx); + + this.setResponseType(this.responseTypes, req, res, ctx); + + if (await this.authenticator.sessionRequiredLocal(req, res, ctx)) { + await this.maybeIngestBody(req, res, ctx); + await this.sessionManager.postAdminSettings(res, ctx, navLinks); + } + } + + /** * Delegate login to authentication module. - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminLogout(req, res, ctx) { const _scope = _fileScope('handlerGetAdminLogout'); this.logger.debug(_scope, 'called', { req, ctx }); + initContext(ctx); + this.setResponseType(this.responseTypes, req, res, ctx); await this.authenticator.sessionOptionalLocal(req, res, ctx); @@ -322,18 +392,17 @@ class Service extends Dingus { /** * Delegate login to authentication module. - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminIA(req, res, ctx) { const _scope = _fileScope('handlerGetAdminIA'); this.logger.debug(_scope, 'called', { req, ctx }); - this.setResponseType(this.responseTypes, req, res, ctx); + initContext(ctx); - // Special case here, to see cookie before session established - ctx.cookie = req.getHeader(Enum.Header.Cookie); + this.setResponseType(this.responseTypes, req, res, ctx); await this.sessionManager.getAdminIA(res, ctx); } diff --git a/src/template/admin-overview-html.js b/src/template/admin-overview-html.js index 1ec3d11..948bdbb 100644 --- a/src/template/admin-overview-html.js +++ b/src/template/admin-overview-html.js @@ -1,17 +1,19 @@ 'use strict'; const th = require('./template-helper'); +const { sessionNavLinks } = require('@squeep/authentication-module'); /** * Show a summary of all topics. - * @param {Object} ctx - * @param {Object[]} ctx.topics - * @param {Object} options - * @param {Object} options.manager - * @param {String} options.manager.pageTitle - * @returns {String} + * @param {object} ctx context + * @param {object[]} ctx.topics topics + * @param {object} options options + * @param {object} options.manager manager options + * @param {string} options.manager.pageTitle page title + * @returns {string} html */ module.exports = (ctx, options) => { + const pagePathLevel = 1; const pageTitle = `${options.manager.pageTitle} - Topics`; const logoUrl = options.manager.logoUrl; const footerEntries = options.manager.footerEntries; @@ -20,10 +22,13 @@ module.exports = (ctx, options) => { } const htmlOptions = { + pageIdentifier: 'admin', pageTitle, logoUrl, footerEntries, }; + th.navLinks(pagePathLevel, ctx, htmlOptions); + sessionNavLinks(pagePathLevel, ctx, htmlOptions); const content = [ `
@@ -33,11 +38,11 @@ module.exports = (ctx, options) => { th.renderTopicRowHeader(), ` `, - ...(ctx.topics && ctx.topics.map((topic) => th.renderTopicRow(topic, { length: topic.subscribers }))), + ...((ctx?.topics || []).map((topic) => th.renderTopicRow(topic, { length: topic.subscribers }))), `
`, ]; - return th.htmlPage(1, ctx, htmlOptions, content); + return th.htmlPage(pagePathLevel, ctx, htmlOptions, content); }; \ No newline at end of file diff --git a/src/template/admin-topic-details-html.js b/src/template/admin-topic-details-html.js index 1d0add0..e239e72 100644 --- a/src/template/admin-topic-details-html.js +++ b/src/template/admin-topic-details-html.js @@ -1,18 +1,20 @@ 'use strict'; const th = require('./template-helper'); +const { sessionNavLinks } = require('@squeep/authentication-module'); /** * Show a topic with all of its subscribers. - * @param {Object} ctx - * @param {Object} ctx.topic - * @param {Object[]} ctx.subscriptions - * @param {Object} options - * @param {Object} options.manager - * @param {String} options.manager.pageTitle - * @returns {String} + * @param {object} ctx context + * @param {object} ctx.topic topic + * @param {object[]} ctx.subscriptions subscriptions + * @param {object} options options + * @param {object} options.manager manager options + * @param {string} options.manager.pageTitle page title + * @returns {string} html */ module.exports = (ctx, options) => { + const pagePathLevel = 2; const pageTitle = `${options.manager.pageTitle} - Topic Details`; const logoUrl = options.manager.logoUrl; const navLinks = [ @@ -27,11 +29,14 @@ module.exports = (ctx, options) => { } const htmlOptions = { + pageIdentifier: 'admin', pageTitle, logoUrl, navLinks, footerEntries, }; + th.navLinks(pagePathLevel, ctx, htmlOptions); + sessionNavLinks(pagePathLevel, ctx, htmlOptions); const content = [ `
@@ -46,7 +51,7 @@ module.exports = (ctx, options) => {
`, `

Topic Publish History — ${ctx.publishCount} updates in the last ${ctx.publishSpan} days

- + histogram of publish history
`, `

${ctx.subscriptions.length ? ctx.subscriptions.length : 'no'} subscription${(ctx.subscriptions.length === 1) ? '' : 's'}

`, @@ -62,11 +67,11 @@ module.exports = (ctx, options) => { th.renderSubscriptionRowHeader(), ` `, - ...(ctx.subscriptions && ctx.subscriptions.map(th.renderSubscriptionRow)), + ...((ctx?.subscriptions || []).map(th.renderSubscriptionRow)), `
`, ]; - return th.htmlPage(2, ctx, htmlOptions, content); + return th.htmlPage(pagePathLevel, ctx, htmlOptions, content); }; \ No newline at end of file diff --git a/src/template/badge-svg.js b/src/template/badge-svg.js index 3ef44d2..7930a1f 100644 --- a/src/template/badge-svg.js +++ b/src/template/badge-svg.js @@ -13,6 +13,12 @@ const ctxDefaults = { }; +/** + * + * @param {number} n number + * @param {number} p precision + * @returns {number} rounded + */ function fixedRound(n, p = 2) { return Number(n.toFixed(p)); } @@ -20,19 +26,21 @@ function fixedRound(n, p = 2) { /** * image/svg+xml;charset=utf-8 formatted badge with subscriber count for a topic - * @param {Object} ctx - badge-specific context (not request context) - * @param {String} label - * @param {String} message - * @param {String} accessibleText - * @returns {String} + * @param {object} ctx - badge-specific context (not request context) + * @param {string} label label + * @param {string} message message + * @param {string} accessibleText accessible text + * @returns {string} svg element */ module.exports = (ctx, label, message, accessibleText) => { - ctx = Object.assign({}, ctxDefaults, ctx, { + ctx = { + ...ctxDefaults, + ...ctx, label, message, accessibleText, - }); + }; ctx.verticalMargin = fixedRound(ctx.height * 0.69); ctx.labelWidth = fixedRound(ctx.label.length * ctx.charWidth); ctx.messageWidth = fixedRound(ctx.message.length * ctx.charWidth); diff --git a/src/template/histogram-svg.js b/src/template/histogram-svg.js index 13d0c91..9f01054 100644 --- a/src/template/histogram-svg.js +++ b/src/template/histogram-svg.js @@ -19,11 +19,23 @@ const optionsDefaults = { maxItems: undefined, }; +/** + * + * @param {number} percent grey value + * @returns {string} rgb value + */ function grey(percent) { const value = Math.round(95 * (1.0 - percent)); return `rgb(${value}%, ${value}%, ${value}%)`; } +/** + * + * @param {object} options options + * @param {number} width width + * @param {number} height height + * @returns {string} svg element + */ function svgHeader(options, width, height) { return [ `\n`; } +/** + * + * @param {object} options options + * @param {number} width width + * @returns {string} element + */ function svgTicks(options, width) { if (!options.tickEvery) { return ''; @@ -68,6 +92,13 @@ function svgTicks(options, width) { \t\n`; } +/** + * + * @param {object} options options + * @param {number} width width + * @param {number} height height + * @returns {string} element + */ function svgLabels(options, width, height) { const labels = []; if (!options.labelHeight) { @@ -85,10 +116,21 @@ function svgLabels(options, width, height) { return labels; } +/** + * @returns {string} element + */ function svgFooter() { return ''; } +/** + * + * @param {object} options options + * @param {number} value value + * @param {number} index index + * @param {number} maxValue max value + * @returns {string} element + */ function svgBar(options, value, index, maxValue) { const id = `i${index}`; const x = options.barWidth * index; @@ -113,7 +155,10 @@ function svgBar(options, value, index, maxValue) { } module.exports = (items, options = {}) => { - options = Object.assign({}, optionsDefaults, options); + options = { + ...optionsDefaults, + ...options, + }; const maxValue = items.reduce((a, b) => Math.max(a, b), 0); const hasLabel = !!options.labelX || !!options.labelZero; diff --git a/src/template/root-html.js b/src/template/root-html.js index 9496c7e..aa5ceba 100644 --- a/src/template/root-html.js +++ b/src/template/root-html.js @@ -1,7 +1,14 @@ 'use strict'; const th = require('./template-helper'); +const { sessionNavLinks } = require('@squeep/authentication-module'); +/** + * + * @param {string} pageTitle page title + * @param {string} logoUrl logo url + * @returns {string} element + */ function hAppSection(pageTitle, logoUrl) { return ` `; } +/** + * @returns {string} element + */ function aboutSection() { return `

What

@@ -21,7 +31,7 @@ function aboutSection() { This is a WebSub Hub service.

- It facilitates the timely distribution of new content from publishers to subscribers. + It facilitates the timely distribution of new content from publishers to subscribers.

`; } +/** + * + * @param {boolean} isPublicHub is public hub + * @param {string} hubURL hub url + * @returns {string} html + */ function usageSection(isPublicHub, hubURL) { const usageContent = isPublicHub ? `

Public Hub

@@ -90,7 +106,7 @@ function usageSection(isPublicHub, hubURL) { -

    +

Publishing Updates

@@ -121,6 +137,11 @@ ${usageContent} `; } +/** + * + * @param {string} contactHTML html + * @returns {string} html + */ function contactSection(contactHTML) { let section = ''; if (contactHTML) { @@ -133,37 +154,37 @@ ${contactHTML} /** * - * @param {Object} ctx - * @param {Object} options - * @param {Object} options.manager - * @param {String} options.adminContactHTML - * @param {String} options.manager.pageTitle - * @param {String} options.manager.publicHub - * @param {Object} options.dingus - * @param {String} options.dingus.selfBaseUrl - * @returns {String} + * @param {object} ctx context + * @param {object} options options + * @param {object} options.manager manager options + * @param {string} options.adminContactHTML html + * @param {string} options.manager.pageTitle title + * @param {string} options.manager.publicHub is public + * @param {object} options.dingus dingus options + * @param {string} options.dingus.selfBaseUrl url + * @returns {string} html */ module.exports = (ctx, options) => { + const pagePathLevel = 0; const pageTitle = options.manager.pageTitle; const isPublicHub = options.manager.publicHub; const contactHTML = options.adminContactHTML; const footerEntries = options.manager.footerEntries; const hubURL = options.dingus.selfBaseUrl || 'https://hub.example.com/'; - const navLinks = [{ - href: 'admin/', - text: 'Admin', - }]; const htmlOptions = { + pageIdentifier: 'root', pageTitle, logoUrl: options.manager.logoUrl, footerEntries, - navLinks, + navLinks: [], }; + th.navLinks(pagePathLevel, ctx, htmlOptions); + sessionNavLinks(pagePathLevel, ctx, htmlOptions); const content = [ aboutSection(), usageSection(isPublicHub, hubURL), contactSection(contactHTML), hAppSection(pageTitle, options.manager.logoUrl), ]; - return th.htmlPage(0, ctx, htmlOptions, content); + return th.htmlPage(pagePathLevel, ctx, htmlOptions, content); }; \ No newline at end of file diff --git a/src/template/template-helper.js b/src/template/template-helper.js index 23b0f12..2da05df 100644 --- a/src/template/template-helper.js +++ b/src/template/template-helper.js @@ -5,10 +5,10 @@ const { Message } = require('../enum'); /** * Render a topic as a row of details. - * @param {Object} topic - * @param {Object[]} subscribers - * @param {Boolean} detailsLink - * @returns {String} + * @param {object} topic topic + * @param {object[]} subscribers subscribers + * @param {boolean} detailsLink link to details + * @returns {string} html */ function renderTopicRow(topic, subscribers, detailsLink = true) { if (!topic) { @@ -38,7 +38,7 @@ function renderTopicRow(topic, subscribers, detailsLink = true) { /** * Render the header row for topic details. - * @returns {String} + * @returns {string} html */ function renderTopicRowHeader() { return ` @@ -63,8 +63,8 @@ function renderTopicRowHeader() { /** * Render a subscription as a row of details. - * @param {Object} subscription - * @returns {String} + * @param {object} subscription subscription + * @returns {string} html */ function renderSubscriptionRow(subscription) { if (!subscription) { @@ -73,7 +73,7 @@ function renderSubscriptionRow(subscription) { `; } return ` - ${subscription.callback} + ${subscription.callback} ${TemplateHelper.dateFormat(subscription.created, Message.EndOfTime, Message.BeginningOfTime, Message.Unknown)} ${TemplateHelper.dateFormat(subscription.verified, Message.EndOfTime, Message.Never, Message.Never)} ${TemplateHelper.dateFormat(subscription.expires, Message.Never, Message.BeginningOfTime, Message.Never)} @@ -91,7 +91,7 @@ function renderSubscriptionRow(subscription) { /** * Render a row of headers for subscription details. - * @returns {String} + * @returns {string} html */ function renderSubscriptionRowHeader() { return ` @@ -114,7 +114,8 @@ function renderSubscriptionRowHeader() { /** * Escape some xml things in strings. - * @param {String} string + * @param {string} string string to escape + * @returns {string} escaped */ function xmlEscape(string) { if (typeof string === 'number') { @@ -133,10 +134,33 @@ function xmlEscape(string) { }[c])); } + +/** + * Add common site links to navigation header. + * @param {number} pagePathLevel depth from root + * @param {object} ctx context + * @param {object} options options + */ +function navLinks(pagePathLevel, ctx, options) { + if (!options.navLinks) { + options.navLinks = []; + } + const rootPath = '../'.repeat(pagePathLevel); + + if (options.pageIdentifier !== 'admin') { + options.navLinks.push({ + text: 'Admin', + href: `${rootPath}admin/`, + }); + } +} + + module.exports = Object.assign(Object.create(TemplateHelper), { + navLinks, xmlEscape, renderTopicRowHeader, renderTopicRow, renderSubscriptionRowHeader, renderSubscriptionRow, -}); \ No newline at end of file +}); diff --git a/src/worker.js b/src/worker.js index ebf8914..4464af4 100644 --- a/src/worker.js +++ b/src/worker.js @@ -11,7 +11,7 @@ const _fileScope = common.fileScope(__filename); */ /** - * @callback Worker~promiseGiver + * @callback PromiseGiver * @param {*} dbCtx * @param {number} atMost * @returns {Promise[]} @@ -19,14 +19,14 @@ const _fileScope = common.fileScope(__filename); class Worker { /** - * @param {object} logger - * @param {object} db - * @param {Worker~promiseGiver} promiseGiver - * @param {object} options - * @param {object} options.worker - * @param {object} options.worker.pollingEnabled - * @param {number} options.worker.recurrSleepMs - * @param {number} options.worker.concurrency + * @param {object} logger logger instance + * @param {object} db db instance + * @param {PromiseGiver} promiseGiver function which fetches and processes work + * @param {object} options options + * @param {object} options.worker worker options + * @param {object} options.worker.pollingEnabled whether to run worker at all + * @param {number} options.worker.recurrSleepMs time between processing runs + * @param {number} options.worker.concurrency how much work to be working on at once */ constructor(logger, db, promiseGiver, options) { this.logger = logger; @@ -41,12 +41,13 @@ class Worker { this.recurrSleepMs = this.options.worker.recurrSleepMs; this.inFlight = []; // Our work heap of Promises this.nextTimeout = undefined; // Allow clearTimeout() to reset waiting period. - this.running = false; + this.running = false; // Worker is running. this.isProcessing = false; // Only let one process() method execute on the work heap at a time } /** * Begin the scheduled loop. + * @param {number} stagger vary startup time by some fraction of recurrence */ start(stagger = 0.618) { const _scope = _fileScope('start'); @@ -77,17 +78,17 @@ class Worker { * results, and use the race as a sort of condvar for checking everything * in the list of what we were waiting for. * NB this means promise cannot be further chained, or it loses the magic. - * @param {Promise} promise + * @param {Promise} promise promise to watch * @returns {Promise} watchedPromise */ static watchedPromise(promise) { - if (Object.prototype.hasOwnProperty.call(promise, 'isSettled')) { + if (Object.hasOwn(promise, 'isSettled')) { return promise; } let isSettled = false; - let resolved = undefined; - let rejected = undefined; + let resolved; + let rejected; promise = promise.then( (res) => { @@ -110,12 +111,17 @@ class Worker { return promise; } + /** + * @callback HandlerFunction + * @param {*} resolved + * @param {*} rejected + * @returns {void} + */ /** * Process the list of promises, removing any which have settled, * and passes their fulfilled values to the handler. - * - * @param {HandlerFunction} handler - * @returns {number} handled + * @param {HandlerFunction} handler invoked on settled promises + * @returns {number} handled promises removed from inFlight list */ _handleWatchedList(handler) { let handled = 0; @@ -133,8 +139,8 @@ class Worker { /** * Refill the workpool with our special promises. - * @param {*} dbCtx - * @returns {Promise[]} + * @param {*} dbCtx db context + * @returns {Promise} wrapped promises */ async _getWork(dbCtx) { const _scope = _fileScope('_getWork'); @@ -151,15 +157,16 @@ class Worker { /** * Simply log results of promises, for now. - * @param {*} resolved - * @param {*} rejected + * @param {*} resolved promise resolution value + * @param {*} rejected promise rejection value */ _watchedHandler(resolved, rejected) { const _scope = _fileScope('_watchedHandler'); - this.logger.debug(_scope, { resolved, rejected }); if (rejected) { - this.logger.error(_scope, { rejected }); + this.logger.error(_scope, 'rejected', { rejected }); + } else { + this.logger.debug(_scope, 'resolved', { resolved }); } } @@ -188,6 +195,7 @@ class Worker { // Interrupt any pending sleep, if we were called out of timeout-cycle. clearTimeout(this.nextTimeout); + this.nextTimeout = undefined; try { await this.db.context(async (dbCtx) => { @@ -203,14 +211,12 @@ class Worker { */ try { await Promise.race(this.inFlight); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars // NOP here, as we'll handle it when we scan the list } - this.logger.debug(_scope, { msg: 'race completed' }); // Address settled promises.. - const settled = this._handleWatchedList(this._watchedHandler.bind(this)); - this.logger.debug(_scope, { settled }); + this._handleWatchedList(this._watchedHandler.bind(this)); // Try to fill the vacancy // TODO: maybe rate-limit this call based on slot availability diff --git a/static/theme.css b/static/theme.css index f6099e2..3939c55 100644 --- a/static/theme.css +++ b/static/theme.css @@ -1,4 +1,3 @@ -* {} html { height: 100vh; } @@ -87,6 +86,9 @@ section + section { .errors ul { border: 1px solid red; } +.otp-key-qr svg { + height: 30vh; +} table { border: 0; width: 100%; diff --git a/test-e2e/fake-servers-client.js b/test-e2e/fake-servers-client.js index 7dfea3b..255fa3f 100644 --- a/test-e2e/fake-servers-client.js +++ b/test-e2e/fake-servers-client.js @@ -4,20 +4,30 @@ * Wrapper interface for controlling fake-servers. */ -const axios = require('axios'); - class FakeClient { constructor(host, subscriberPort, topicPort) { this.logger = console; this.host = host; this.subscriberPort = subscriberPort; this.topicPort = topicPort; - this.axios = axios.create({ - validateStatus: (statusCode) => (Math.floor(statusCode / 100)) === 2, - headers: { - 'User-Agent': 'FakeClient', - }, - }); + this.Got = undefined; + this.got = this._init.bind(this); + } + + async _init(...args) { + if (!this.Got) { + // eslint-disable-next-line + this.Got = await import('got'); + this.got = this.Got.got.extend({ + headers: { + 'User-Agent': 'FakeClient', + }, + responseType: 'text', + }); + } + if (args.length) { + return this.got(...args); + } } topicUrl(id) { @@ -28,42 +38,43 @@ class FakeClient { return `http://${this.host}:${this.subscriberPort}/subscriber/${id}${extra}`; } - static _axiosRequestConfig(method, url, params = {}, headers = {}, data) { - const urlObj = new URL(url); - const config = { + static _requestConfig(method, url, params = {}, headers = {}, body = undefined) { + const gotConfig = { method, - url: `${urlObj.origin}${urlObj.pathname}`, - params: urlObj.searchParams, + url: new URL(url), headers, - ...(data && { data }), - responseType: 'text', - transformResponse: [ (res) => res ], + ...(body && { body }), }; - Object.entries(params).map(([k, v]) => config.params.set(k, v)); - return config; + Object.entries(params).forEach(([k, v]) => gotConfig.url.searchParams.set(k, v)); + return gotConfig; + } + + static _formData(obj) { + return Object.entries(obj) + .map((entry) => entry.map(encodeURIComponent).join('=')) + .join('&') + ; } async subscribe(hubUrl, subscriberId, topicId, postData = {}) { const topicUrl = this.topicUrl(topicId); const subscriberUrl = this.subscriberUrl(subscriberId); - const data = { + const data = FakeClient._formData({ 'hub.callback': subscriberUrl, 'hub.mode': 'subscribe', 'hub.topic': topicUrl, 'hub.lease_seconds': 60, 'hub.secret': 'sharedSecret', ...postData, - }; - const formData = new URLSearchParams(data).toString(); - const headers = { + }); + const config = FakeClient._requestConfig('POST', hubUrl, {}, { 'Content-Type': 'application/x-www-form-urlencoded', - }; - + }, data); try { - return this.axios(FakeClient._axiosRequestConfig('POST', hubUrl, {}, headers, formData)); - } catch (e) { - this.logger.error('subscribe', e); - throw e; + return await this.got(config); + } catch (error) { + this.logger.error('subscribe', error, config); + throw error; } } @@ -83,14 +94,15 @@ class FakeClient { contentType: 'text/plain', }; const url = this.topicUrl(id); + const config = FakeClient._requestConfig('PUT', url, { + ...defaultBehavior, + ...behavior, + }); try { - return this.axios(FakeClient._axiosRequestConfig('PUT', url, { - ...defaultBehavior, - ...behavior, - })); - } catch (e) { - this.logger.error('topicSet', e); - throw e; + return await this.got(config); + } catch (error) { + this.logger.error('topicSet', error, config); + throw error; } } @@ -99,12 +111,13 @@ class FakeClient { * @param {String} id */ async topicDelete(id) { - const url =this.topicUrl(id); + const url = this.topicUrl(id); + const config = FakeClient._requestConfig('DELETE', url); try { - return this.axios(FakeClient._axiosRequestConfig('DELETE', url)); - } catch (e) { - this.logger.error('topicDelete', e); - throw e; + return await this.got(config); + } catch (error) { + this.logger.error('topicDelete', error, config); + throw error; } } @@ -121,14 +134,15 @@ class FakeClient { matchChallenge: true, }; const url = this.subscriberUrl(id, '/verify'); + const config = FakeClient._requestConfig('PUT', url, { + ...defaultBehavior, + ...behavior, + }); try { - return this.axios(FakeClient._axiosRequestConfig('PUT', url, { - ...defaultBehavior, - ...behavior, - })); - } catch (e) { - this.logger.error('subscriberSetVerify', e); - throw e; + return await this.got(config); + } catch (error) { + this.logger.error('subscriberSetVerify', error, config); + throw error; } } @@ -138,19 +152,20 @@ class FakeClient { * @param {Object} behavior * @param {Number} behavior.statusCode */ - async subscriberSetContent(id, behavior = {}) { - const defaultBehavior = { - statusCode: 200, - }; + async subscriberSetContent(id, behavior = {}) { + const defaultBehavior = { + statusCode: 200, + }; const url = this.subscriberUrl(id, '/content'); + const config = FakeClient._requestConfig('PUT', url, { + ...defaultBehavior, + ...behavior, + }); try { - return this.axios(FakeClient._axiosRequestConfig('PUT', url, { - ...defaultBehavior, - ...behavior, - })); - } catch (e) { - this.logger.error('subscriberSetContent', e); - throw e; + return await this.got(config); + } catch (error) { + this.logger.error('subscriberSetContent', error, config); + throw error; } } @@ -160,11 +175,12 @@ class FakeClient { */ async subscriberDelete(id) { const url = this.subscriberUrl(id); + const config = FakeClient._requestConfig('DELETE', url); try { - return this.axios(FakeClient._axiosRequestConfig('DELETE', url)); - } catch (e) { - this.logger.error('subscriberDelete', e); - throw e; + return await this.got(config); + } catch (error) { + this.logger.error('subscriberDelete', error, config); + throw error; } } diff --git a/test-e2e/fake-servers.js b/test-e2e/fake-servers.js index 9d46d48..2071962 100644 --- a/test-e2e/fake-servers.js +++ b/test-e2e/fake-servers.js @@ -46,7 +46,7 @@ class TopicFake extends Dingus { res.setHeader('Link', behavior.selfLink + (behavior.hubLink ? `, ${behavior.hubLink}` : '')); res.statusCode = behavior.statusCode; res.end(behavior.content); - this.logger.info({ method: req.method, statusCode: res.statusCode, url: req.url }); + this.logger.info('TopicFake:getId', { method: req.method, statusCode: res.statusCode, url: req.url }); } async putId(req, res, ctx) { @@ -61,6 +61,7 @@ class TopicFake extends Dingus { }; this.topicBehaviors.set(id, behavior); res.statusCode = 200; + this.logger.info('TopicFake:putId', { method: req.method, statusCode: res.statusCode, url: req.url }); res.end(); } @@ -68,6 +69,7 @@ class TopicFake extends Dingus { this.setResponseType(this.responseTypes, req, res, ctx); this.topicBehaviors.delete(ctx.params.id); res.statusCode = 200; + this.logger.info('TopicFake:deleteId', { method: req.method, statusCode: res.statusCode, url: req.url }); res.end(); } @@ -97,9 +99,9 @@ class SubscriberFake extends Dingus { this.setResponseType(this.responseTypes, req, res, ctx); const behavior = this.verifyBehaviors.get(ctx.params.id); res.statusCode = behavior ? behavior.statusCode : 404; - const response = (behavior && behavior.matchChallenge) ? ctx.queryParams['hub.challenge'] : (behavior && behavior.response); + const response = (behavior?.matchChallenge) ? ctx.queryParams['hub.challenge'] : (behavior?.response); res.end(response); - this.logger.info({ method: req.method, statusCode: res.statusCode, matchChallenge: !!(behavior && behavior.matchChallenge), url: req.url }); + this.logger.info('SubscriberFake:getId', { method: req.method, statusCode: res.statusCode, matchChallenge: !!(behavior?.matchChallenge), url: req.url }); } async postId(req, res, ctx) { @@ -112,7 +114,7 @@ class SubscriberFake extends Dingus { behavior.content = ctx.rawBody; } res.end(); - this.logger.info({ content: behavior && behavior.content, method: req.method, statusCode: res.statusCode, matchChallenge: !!(behavior && behavior.matchChallenge), url: req.url }); + this.logger.info('SubscriberFake:postId', { content: behavior?.content, method: req.method, statusCode: res.statusCode, matchChallenge: !!(behavior?.matchChallenge), url: req.url }); } async putVerify(req, res, ctx) { @@ -129,6 +131,7 @@ class SubscriberFake extends Dingus { } res.statusCode = 200; res.end(); + this.logger.info('SubscriberFake:putVerify', { method: req.method, statusCode: res.statusCode, url: req.url }); } async putContent(req, res, ctx) { @@ -139,6 +142,7 @@ class SubscriberFake extends Dingus { this.contentBehaviors.set(ctx.params.id, behavior); res.statusCode = 200; res.end(); + this.logger.info('SubscriberFake:putContent', { method: req.method, statusCode: res.statusCode, url: req.url }); } async deleteId(req, res, ctx) { @@ -147,6 +151,7 @@ class SubscriberFake extends Dingus { this.verifyBehaviors.delete(ctx.params.id); res.statusCode = 200; res.end(); + this.logger.info('SubscriberFake:deleteId', { method: req.method, statusCode: res.statusCode, url: req.url }); } } // SubscriberFake diff --git a/test-e2e/test-many.js b/test-e2e/test-many.js index 1ff40c9..bc14962 100644 --- a/test-e2e/test-many.js +++ b/test-e2e/test-many.js @@ -1,7 +1,6 @@ 'use strict'; -const assert = require('assert'); -const uuid = require('uuid'); +const crypto = require('crypto'); const FakeServersClient = require('./fake-servers-client'); const subscriberPort = process.env.FAKE_SUBSCRIBER_PORT || 9876; @@ -14,14 +13,14 @@ const hubUrl = `http://${hubAddress}:${hubPort}/`; const client = new FakeServersClient(listenAddress, subscriberPort, topicPort); async function newTopic() { - const id = uuid.v4(); + const id = crypto.randomUUID(); await client.topicSet(id, { hubUrl }); console.log('created fake topic', id); return id; } async function newSubscriber() { - const id = uuid.v4(); + const id = crypto.randomUUID(); await client.subscriberSetVerify(id); console.log('created fake subscriber', id); return id; diff --git a/test-e2e/test-one.js b/test-e2e/test-one.js index 8c6fdf2..e051983 100644 --- a/test-e2e/test-one.js +++ b/test-e2e/test-one.js @@ -1,7 +1,6 @@ 'use strict'; -const assert = require('assert'); -const uuid = require('uuid'); +const crypto = require('crypto'); const FakeServersClient = require('./fake-servers-client'); const subscriberPort = process.env.FAKE_SUBSCRIBER_PORT || 9876; @@ -14,14 +13,14 @@ const hubUrl = `http://${hubAddress}:${hubPort}/`; const client = new FakeServersClient(listenAddress, subscriberPort, topicPort); async function newTopic() { - const id = uuid.v4(); + const id = crypto.randomUUID(); await client.topicSet(id, { hubUrl }); console.log('created fake topic', id); return id; } async function newSubscriber() { - const id = uuid.v4(); + const id = crypto.randomUUID(); await client.subscriberSetVerify(id); console.log('created fake subscriber', id); return id; @@ -32,7 +31,7 @@ async function newSubscriber() { const subscriberId = await newSubscriber(); const result = await client.subscribe(hubUrl, subscriberId, topicId); - console.log('subscribed', { status: result.status, headers: result.headers, data: result.data }); + console.log('subscribed', { status: result.statusCode, headers: result.headers, body: result.body }); console.log('done'); })().catch((e) => { diff --git a/test/lint-html.js b/test/lint-html.js index 4b5cd47..a750808 100644 --- a/test/lint-html.js +++ b/test/lint-html.js @@ -1,13 +1,9 @@ 'use strict'; -const assert = require('assert'); +const { makeHtmlLint } = require('@squeep/html-template-helper'); +const { HtmlValidate } = require('html-validate'); const stubLogger = require('./stub-logger'); -const { lint } = require('html-minifier-lint'); // eslint-disable-line node/no-unpublished-require - -function lintHtml(html) { - const result = lint(html); - stubLogger.debug('lintHtml', '', { result, html }); - assert(!result); -} +const htmlValidate = new HtmlValidate(); +const lintHtml = makeHtmlLint(stubLogger, htmlValidate); module.exports = lintHtml; diff --git a/test/src/common.js b/test/src/common.js index a9b228c..45e9d2c 100644 --- a/test/src/common.js +++ b/test/src/common.js @@ -1,7 +1,6 @@ -/* eslint-env mocha */ 'use strict'; -const assert = require('assert'); +const assert = require('node:assert'); const common = require('../../src/common'); describe('Common', function () { @@ -23,47 +22,71 @@ describe('Common', function () { }); }); // freezeDeep - describe('axiosResponseLogData', function () { + describe('gotResponseLogData', function () { it('covers', function () { const response = { - status: 200, - statusText: 'OK', + statusCode: 200, + statusMessage: 'OK', headers: { 'Content-Type': 'text/plain', }, otherData: 'blah', - data: 'Old Mother West Wind had stopped to talk with the Slender Fir Tree. "I\'ve just come across the Green Meadows," said Old Mother West Wind, “and there I saw the Best Thing in the World.”', + body: 'Old Mother West Wind had stopped to talk with the Slender Fir Tree. "I\'ve just come across the Green Meadows," said Old Mother West Wind, “and there I saw the Best Thing in the World.”', + timings: { + phases: { + total: 87, + }, + }, + retryCount: 2, + redirectUrls: ['https://example.com/clip/Thornton_Burgess'], }; const expected = { - status: 200, - statusText: 'OK', + statusCode: 200, + statusMessage: 'OK', headers: { 'Content-Type': 'text/plain', }, - data: 'Old Mother West Wind had stopped to talk with the Slender Fir Tree. "I\'ve just come across the Green... (184 bytes)', + body: 'Old Mother West Wind had stopped to talk with the Slender Fir Tree. "I\'ve just come across the Green... (184 bytes)', + elapsedTimeMs: 87, + retryCount: 2, + redirectUrls: ['https://example.com/clip/Thornton_Burgess'], + }; + const result = common.gotResponseLogData(response); + assert.deepStrictEqual(result, expected); + }); + it('covers buffer data', function () { + const response = { + statusCode: 200, + statusMessage: 'OK', + body: Buffer.from('Old Mother West Wind had stopped to talk with the Slender Fir Tree. "I\'ve just come across the Green Meadows," said Old Mother West Wind, “and there I saw the Best Thing in the World.”'), + }; + const expected = { + statusCode: 200, + statusMessage: 'OK', + body: '', }; - const result = common.axiosResponseLogData(response); + const result = common.gotResponseLogData(response); assert.deepStrictEqual(result, expected); }); it('covers no data', function () { const response = { - status: 200, - statusText: 'OK', + statusCode: 200, + statusMessage: 'OK', headers: { 'Content-Type': 'text/plain', }, }; const expected = { - status: 200, - statusText: 'OK', + statusCode: 200, + statusMessage: 'OK', headers: { 'Content-Type': 'text/plain', }, }; - const result = common.axiosResponseLogData(response); + const result = common.gotResponseLogData(response); assert.deepStrictEqual(result, expected); }); - }); // axiosResponseLogData + }); // gotResponseLogData describe('topicLeaseDefaults', function () { it('supplies necessary properties', function () { @@ -110,7 +133,7 @@ describe('Common', function () { it('covers default', function () { const result = common.attemptRetrySeconds(0); assert(result >= 60); - assert(result <= 60 * 1.618) + assert(result <= 60 * 1.618); }); }); // attemptRetrySeconds diff --git a/test/src/communication.js b/test/src/communication.js index d5ebe54..69f0453 100644 --- a/test/src/communication.js +++ b/test/src/communication.js @@ -1,10 +1,7 @@ -/* eslint-env mocha */ -/* eslint-disable capitalized-comments, sonarjs/no-duplicate-string */ - 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const assert = require('node:assert'); +const sinon = require('sinon'); const Communication = require('../../src/communication'); const Config = require('../../config'); @@ -37,20 +34,23 @@ describe('Communication', function () { communication = new Communication(stubLogger, stubDb, options); }); - describe('Axios timing coverage', function () { - const request = {}; - const response = { - config: request, - }; - it('tags request', function () { - communication.axios.interceptors.request.handlers[0].fulfilled(request); - assert(request.startTimestampMs); + describe('_init', function () { + it('covers', async function () { + await communication._init(); + await communication._init(); + assert(communication.Got); + assert(communication.got); }); - it('tags response', function () { - communication.axios.interceptors.response.handlers[0].fulfilled(response); - assert(response.elapsedTimeMs); + }); + + describe('_onRetry', function () { + it('covers', function () { + const error = {}; + const retryCount = 1; + communication._onRetry(error, retryCount); + assert(communication.logger.debug.called); }); - }); // Axios timing coverage + }); describe('userAgentString', function () { it('has default behavior', function () { @@ -110,134 +110,8 @@ describe('Communication', function () { it('hashes', function () { const result = Communication.contentHash(content, algorithm); assert.strictEqual(result, expected); - }) - }); - - describe('Axios Configurations', function () { - let requestUrl, expectedUrl, topicUrl; - beforeEach(function () { - requestUrl = 'https://example.com/callback/?id=123'; - expectedUrl = 'https://example.com/callback/'; - topicUrl = 'http://example.com/blog/'; - }); - it('_axiosConfig', function () { - const method = 'GET'; - const contentType = 'text/plain'; - const body = undefined; - const params = { - 'extra_parameter': 'foobar', - }; - const expectedUrlObj = new URL('https://example.com/callback/?id=123&extra_parameter=foobar'); - const expected = { - method, - url: 'https://example.com/callback/', - headers: { - 'Content-Type': 'text/plain', - }, - params: expectedUrlObj.searchParams, - responseType: 'text', - }; - const result = Communication._axiosConfig(method, requestUrl, body, params, { - 'Content-Type': contentType, - }); - delete result.transformResponse; - assert.deepStrictEqual(result, expected); - }); - it('_axiosConfig covers defaults', function () { - const method = 'OPTIONS'; - const expectedUrlObj = new URL(requestUrl); - const expected = { - method, - url: expectedUrl, - headers: {}, - params: expectedUrlObj.searchParams, - responseType: 'text', - }; - const result = Communication._axiosConfig(method, requestUrl); - delete result.transformResponse; - assert.deepStrictEqual(result, expected); - }); - it('covers null response transform', function () { - const result = Communication._axiosConfig('GET', 'https://example.com/', undefined, {}, {}); - result.transformResponse[0](); - }); - it('_intentVerifyAxiosConfig', function () { - const mode = 'subscribe'; - const leaseSeconds = 864000; - const challenge = 'abcxyz'; - const expectedUrlObj = new URL(`${requestUrl}&hub.mode=${mode}&hub.topic=${encodeURIComponent(topicUrl)}&hub.challenge=${challenge}&hub.lease_seconds=${leaseSeconds}`); - const expected = { - method: 'GET', - url: expectedUrl, - headers: {}, - params: expectedUrlObj.searchParams, - responseType: 'text', - }; - const result = Communication._intentVerifyAxiosConfig(requestUrl, topicUrl, mode, leaseSeconds, challenge); - delete result.transformResponse; - assert.deepStrictEqual(result, expected); - }); - it('_intentDenyAxiosConfig', function () { - const reason = 'something'; - const expectedUrlObj = new URL(`${requestUrl}&hub.mode=denied&hub.topic=${encodeURIComponent(topicUrl)}&hub.reason=${reason}`); - const expected = { - method: 'GET', - url: expectedUrl, - headers: {}, - params: expectedUrlObj.searchParams, - responseType: 'text', - }; - const result = Communication._intentDenyAxiosConfig(requestUrl, topicUrl, reason); - delete result.transformResponse; - assert.deepStrictEqual(result, expected); - }); - it('_publisherValidationAxiosConfig', function () { - const topic = { - url: topicUrl, - publisherValidationUrl: 'https://example.com/publisher/', - }; - const verification = { - callback: requestUrl, - topic: topicUrl, - }; - const expectedUrlObj = new URL(topic.publisherValidationUrl); - const expected = { - method: 'POST', - url: topic.publisherValidationUrl, - data: { - callback: requestUrl, - topic: topicUrl, - }, - headers: { - 'Content-Type': 'application/json', - }, - params: expectedUrlObj.searchParams, - responseType: 'text', - }; - const result = Communication._publisherValidationAxiosConfig(topic, verification); - delete result.transformResponse; - assert.deepStrictEqual(result, expected); - }); - it('_topicFetchAxiosConfig', function () { - const topic = { - url: topicUrl, - contentType: 'text/plain', - }; - const expectedUrlObj = new URL(topicUrl); - const expected = { - method: 'GET', - url: topicUrl, - params: expectedUrlObj.searchParams, - headers: { - Accept: 'text/plain, */*;q=0.9', - }, - responseType: 'text', - }; - const result = Communication._topicFetchAxiosConfig(topic); - delete result.transformResponse; - assert.deepStrictEqual(result, expected); }); - }); // Axios Configurations + }); describe('verificationProcess', function () { const challenge = 'a_challenge'; @@ -263,13 +137,13 @@ describe('Communication', function () { sinon.stub(Communication, 'generateChallenge').resolves(challenge); sinon.stub(communication, 'publisherValidate').resolves(true); - sinon.stub(communication, 'axios').resolves({ - status: 200, - statusText: 'OK', + sinon.stub(communication, 'got').resolves({ + statusCode: 200, + statusMessage: 'OK', headers: { 'content-type': 'text/plain', }, - data: challenge, + body: challenge, }); communication.db.verificationGetById.resolves(verification); @@ -312,7 +186,7 @@ describe('Communication', function () { await communication.verificationProcess(dbCtx, callback, topicId, requestId); assert(communication.db.verificationRelease.called); - assert(!communication.axios.called); + assert(!communication.got.called); }); it('denies subscription to deleted topic', async function () { @@ -357,8 +231,8 @@ describe('Communication', function () { }); it('handles request error', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').throws(new Error()); + communication.got.restore(); + sinon.stub(communication, 'got').rejects(new Error()); await communication.verificationProcess(dbCtx, callback, topicId, requestId); @@ -366,9 +240,9 @@ describe('Communication', function () { }); it('handles 500 response', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 500, + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 500, }); await communication.verificationProcess(dbCtx, callback, topicId, requestId); @@ -377,9 +251,9 @@ describe('Communication', function () { }); it('handles non-200 response', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 400, + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 400, }); await communication.verificationProcess(dbCtx, callback, topicId, requestId); @@ -426,14 +300,14 @@ describe('Communication', function () { communication.db.verificationGetById.restore(); verification.mode = 'unsubscribe'; sinon.stub(communication.db, 'verificationGetById').resolves(verification); - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 200, - statusText: 'OK', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 200, + statusMessage: 'OK', headers: { 'content-type': 'text/plain', }, - data: 'not the challenge', + body: 'not the challenge', }); await communication.verificationProcess(dbCtx, callback, topicId, requestId); @@ -470,9 +344,9 @@ describe('Communication', function () { httpRemoteAddr: '127.0.0.0', }; - sinon.stub(communication, 'axios').resolves({ - status: 200, - statusText: 'OK', + sinon.stub(communication, 'got').resolves({ + statusCode: 200, + statusMessage: 'OK', headers: { 'content-type': 'application/json', }, @@ -491,10 +365,10 @@ describe('Communication', function () { }); it('succeeds with rejection', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 400, - statusText: 'Bad Request', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 400, + statusMessage: 'Bad Request', headers: { 'content-type': 'application/json', }, @@ -508,10 +382,10 @@ describe('Communication', function () { }); it('defers on request server error', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 502, - statusText: 'Bad Gateway', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 502, + statusMessage: 'Bad Gateway', headers: { 'content-type': 'text/plain', }, @@ -523,8 +397,8 @@ describe('Communication', function () { }); it('handles request error', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').throws(new Error()); + communication.got.restore(); + sinon.stub(communication, 'got').rejects(new Error()); const result = await communication.publisherValidate(dbCtx, topic, verification); @@ -546,16 +420,16 @@ describe('Communication', function () { requestId = '7d37ea20-4ef7-417e-a08d-c0ba71269ab1'; topicId = '234ec6fb-f1cd-4ac3-8ea9-29ed42ae0e21'; - sinon.stub(communication, 'axios').resolves({ - status: 200, - statusText: 'OK', + sinon.stub(communication, 'got').resolves({ + statusCode: 200, + statusMessage: 'OK', headers: { 'content-type': 'text/plain', link: '; rel="hub"', 'last-modified': 'Thu, 18 Nov 2021 20:34:35 GMT', 'etag': '"9c104-1673e-5d1161636d742"', }, - data: 'Jackdaws love my big sphinx of quartz.', + body: 'Jackdaws love my big sphinx of quartz.', }); communication.db.topicGetById.resolves(topic); @@ -580,12 +454,12 @@ describe('Communication', function () { await communication.topicFetchProcess(dbCtx, topicId, requestId); - assert(!communication.axios.called); + assert(!communication.got.called); }); it('handles request error', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').throws(new Error()); + communication.got.restore(); + sinon.stub(communication, 'got').rejects(new Error()); await communication.topicFetchProcess(dbCtx, topicId, requestId); @@ -593,10 +467,10 @@ describe('Communication', function () { }); it('handles 500 response', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 500, - statusText: 'Internal Server Error', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 500, + statusMessage: 'Internal Server Error', headers: { 'content-type': 'text/plain', }, @@ -608,10 +482,10 @@ describe('Communication', function () { }); it('handles bad response', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 404, - statusText: 'Not Found', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 404, + statusMessage: 'Not Found', headers: { 'content-type': 'text/plain', }, @@ -637,8 +511,8 @@ describe('Communication', function () { topic.httpLastModified = 'Thu, 18 Nov 2021 20:34:35 GMT'; topic.httpEtag = '"9c104-1673e-5d1161636d742"'; communication.db.topicGetById.resolves(topic); - communication.axios.resolves({ - status: 304, + communication.got.resolves({ + statusCode: 304, }); await communication.topicFetchProcess(dbCtx, topicId, requestId); @@ -655,15 +529,15 @@ describe('Communication', function () { }); it('updates content with lax link enforcement', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 200, - statusText: 'OK', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 200, + statusMessage: 'OK', headers: { 'content-type': 'text/plain', link: '; rel="hub"', }, - data: 'Jackdaws love my big sphinx of quartz.', + body: 'Jackdaws love my big sphinx of quartz.', }); communication.options.communication.strictTopicHubLink = false; @@ -675,15 +549,15 @@ describe('Communication', function () { }); it('deletes topic when hub relation unsatisfied', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 200, - statusText: 'OK', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 200, + statusMessage: 'OK', headers: { 'content-type': 'text/plain', link: '; rel="hub"', }, - data: 'Jackdaws love my big sphinx of quartz.', + body: 'Jackdaws love my big sphinx of quartz.', }); await communication.topicFetchProcess(dbCtx, topicId, requestId); @@ -714,13 +588,13 @@ describe('Communication', function () { signatureAlgorithm: 'sha512', }; - sinon.stub(communication, 'axios').resolves({ - status: 200, - statusText: 'OK', + sinon.stub(communication, 'got').resolves({ + statusCode: 200, + statusMessage: 'OK', headers: { 'content-type': 'text/plain', }, - data: 'Jackdaws love my big sphinx of quartz.', + body: 'Jackdaws love my big sphinx of quartz.', }); communication.db.topicGetContentById.resolves(topic); @@ -756,8 +630,8 @@ describe('Communication', function () { }); it('handles request error', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').throws(); + communication.got.restore(); + sinon.stub(communication, 'got').throws(); await communication.subscriptionDeliveryProcess(dbCtx, subscriptionId, requestId); @@ -765,10 +639,10 @@ describe('Communication', function () { }); it('handles 5xx response', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 500, - statusText: 'Internal Server Error', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 500, + statusMessage: 'Internal Server Error', headers: { 'content-type': 'text/plain', }, @@ -780,10 +654,10 @@ describe('Communication', function () { }); it('handles 4xx response', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 404, - statusText: 'Not Found', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 404, + statusMessage: 'Not Found', headers: { 'content-type': 'text/plain', }, @@ -795,10 +669,10 @@ describe('Communication', function () { }); it('handles 410 response', async function () { - communication.axios.restore(); - sinon.stub(communication, 'axios').resolves({ - status: 410, - statusText: 'Gone', + communication.got.restore(); + sinon.stub(communication, 'got').resolves({ + statusCode: 410, + statusMessage: 'Gone', headers: { 'content-type': 'text/plain', }, @@ -832,14 +706,14 @@ describe('Communication', function () { it('covers claim', async function () { communication.db.topicFetchClaimById.resolves({ changes: 1, - }) + }); await communication.topicFetchClaimAndProcessById(dbCtx, topicId, requestId); assert(communication.topicFetchProcess.called); }); it('covers no claim', async function () { communication.db.topicFetchClaimById.resolves({ changes: 0, - }) + }); await communication.topicFetchClaimAndProcessById(dbCtx, topicId, requestId); assert(!communication.topicFetchProcess.called); }); @@ -856,14 +730,14 @@ describe('Communication', function () { it('covers claim', async function () { communication.db.verificationClaimById.resolves({ changes: 1, - }) + }); await communication.verificationClaimAndProcessById(dbCtx, verificationId, requestId); assert(communication.verificationProcess.called); }); it('covers no claim', async function () { communication.db.verificationClaimById.resolves({ changes: 0, - }) + }); await communication.verificationClaimAndProcessById(dbCtx, verificationId, requestId); assert(!communication.verificationProcess.called); }); diff --git a/test/src/db/base.js b/test/src/db/base.js index 74e5834..1f2d719 100644 --- a/test/src/db/base.js +++ b/test/src/db/base.js @@ -1,8 +1,7 @@ -/* eslint-env mocha */ 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const assert = require('node:assert'); +const sinon = require('sinon'); const stubDB = require('../../stub-db'); const stubLogger = require('../../stub-logger'); diff --git a/test/src/db/factory.js b/test/src/db/factory.js index 7b9402c..d26d51a 100644 --- a/test/src/db/factory.js +++ b/test/src/db/factory.js @@ -1,18 +1,17 @@ -/* eslint-env mocha */ 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require -const common = require('../../../src/common'); +const assert = require('node:assert'); +const sinon = require('sinon'); const DB = require('../../../src/db'); const DBErrors = require('../../../src/db/errors'); const DatabasePostgres = require('../../../src/db/postgres'); const DatabaseSQLite = require('../../../src/db/sqlite'); +const stubLogger = require('../../stub-logger'); describe('DatabaseFactory', function () { let logger, options; beforeEach(function () { - logger = common.nullLogger; + logger = stubLogger, options = { db: { connectionString: '', diff --git a/test/src/db/integration.js b/test/src/db/integration.js index bd28e92..eed37e2 100644 --- a/test/src/db/integration.js +++ b/test/src/db/integration.js @@ -1,5 +1,3 @@ -/* eslint-env mocha */ -/* eslint-disable sonarjs/no-identical-functions */ 'use strict'; /** @@ -16,8 +14,8 @@ * */ -const assert = require('assert'); -const { step } = require('mocha-steps'); // eslint-disable-line node/no-unpublished-require +const assert = require('node:assert'); +const { step } = require('mocha-steps'); const stubLogger = require('../../stub-logger'); const DBErrors = require('../../../src/db/errors'); const testData = require('../../test-data/db-integration'); @@ -85,33 +83,51 @@ describe('Database Integration', function () { }); describe('Authentication', function () { - let identifier, credential; + let identifier, credential, otpKey; beforeEach(function () { identifier = 'username'; credential = 'myEncryptedPassword'; + otpKey = '1234567890123456789012'; }); - step('create auth entry', async function() { + step('create auth entry', async function () { await db.context(async (dbCtx) => { await db.authenticationUpsert(dbCtx, identifier, credential); }); }); - step('get auth entry', async function() { + step('get auth entry', async function () { await db.context(async (dbCtx) => { const authInfo = await db.authenticationGet(dbCtx, identifier); assert.strictEqual(authInfo.credential, credential); }); }); - step('valid auth event', async function() { + step('valid auth event', async function () { await db.context(async (dbCtx) => { await db.authenticationSuccess(dbCtx, identifier); const authInfo = await db.authenticationGet(dbCtx, identifier); assert.notStrictEqual(authInfo.lastAuthentication, undefined); }); }); - step('update auth entry', async function() { + step('update auth entry', async function () { await db.context(async (dbCtx) => { credential = 'myNewPassword'; - await db.authenticationUpsert(dbCtx, identifier, credential); + await db.authenticationUpsert(dbCtx, identifier, credential, otpKey); + const authInfo = await db.authenticationGet(dbCtx, identifier); + assert.strictEqual(authInfo.credential, credential); + assert.strictEqual(authInfo.otpKey, otpKey); + }); + }); + step('update auth otp key', async function () { + await db.context(async (dbCtx) => { + const removedOTPKey = null; + await db.authenticationUpdateOTPKey(dbCtx, identifier, removedOTPKey); + const authInfo = await db.authenticationGet(dbCtx, identifier); + assert.strictEqual(authInfo.otpKey, removedOTPKey); + }); + }); + step('update credential', async function () { + await db.context(async (dbCtx) => { + credential = '$plain$anotherCredential'; + await db.authenticationUpdateCredential(dbCtx, identifier, credential); const authInfo = await db.authenticationGet(dbCtx, identifier); assert.strictEqual(authInfo.credential, credential); }); @@ -285,7 +301,7 @@ describe('Database Integration', function () { const data = { ...testData.subscriptionUpsert, topicId, - } + }; await db.context(async (dbCtx) => { const result = await db.subscriptionUpsert(dbCtx, data); assert(result.lastInsertRowid); @@ -364,7 +380,7 @@ describe('Database Integration', function () { ...testData.subscriptionUpsert, secret: 'newSecret', topicId, - } + }; await db.context(async (dbCtx) => { const result = await db.subscriptionUpsert(dbCtx, data); assert(result.lastInsertRowid); @@ -416,7 +432,7 @@ describe('Database Integration', function () { }); step('delete expired subscriptions', async function() { await db.context(async (dbCtx) => { - await db.subscriptionDeleteExpired(dbCtx, topicId) + await db.subscriptionDeleteExpired(dbCtx, topicId); const subscription = await db.subscriptionGet(dbCtx, testData.subscriptionUpsert.callback, topicId); assert(!subscription); }); diff --git a/test/src/db/postgres-listener.js b/test/src/db/postgres-listener.js index ecd2fe2..7170d50 100644 --- a/test/src/db/postgres-listener.js +++ b/test/src/db/postgres-listener.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict'; -const assert = require('assert'); +const assert = require('node:assert'); const sinon = require('sinon'); const stubLogger = require('../../stub-logger'); const Listener = require('../../../src/db/postgres/listener'); diff --git a/test/src/db/postgres.js b/test/src/db/postgres.js index d6bf674..825a295 100644 --- a/test/src/db/postgres.js +++ b/test/src/db/postgres.js @@ -1,12 +1,8 @@ -/* eslint-disable sonarjs/no-identical-functions */ -/* eslint-env mocha */ -/* eslint-disable sonarjs/no-duplicate-string */ 'use strict'; /* This provides implementation coverage, stubbing pg-promise. */ -const assert = require('assert'); -// eslint-disable-next-line node/no-unpublished-require +const assert = require('node:assert'); const sinon = require('sinon'); const DBStub = require('../../stub-db'); const stubLogger = require('../../stub-logger'); @@ -65,7 +61,7 @@ describe('DatabasePostgres', function () { httpRemoteAddr = '127.0.0.1'; httpFrom = 'user@example.com'; wanted = 5; -}); + }); afterEach(function () { sinon.restore(); }); @@ -490,10 +486,11 @@ describe('DatabasePostgres', function () { }); // authenticationGet describe('authenticationUpsert', function () { - let identifier, credential; + let identifier, credential, otpKey; beforeEach(function () { identifier = 'username'; credential = '$z$foo'; + otpKey = '12345678901234567890123456789012'; }); it('success', async function () { const dbResult = { @@ -502,7 +499,7 @@ describe('DatabasePostgres', function () { duration: 22, }; sinon.stub(db.db, 'result').resolves(dbResult); - await db.authenticationUpsert(dbCtx, identifier, credential); + await db.authenticationUpsert(dbCtx, identifier, credential, otpKey); }); it('failure', async function() { credential = undefined; @@ -513,7 +510,7 @@ describe('DatabasePostgres', function () { }; sinon.stub(db.db, 'result').resolves(dbResult); try { - await db.authenticationUpsert(dbCtx, identifier, credential); + await db.authenticationUpsert(dbCtx, identifier, credential, otpKey); assert.fail(noExpectedException); } catch (e) { assert(e instanceof DBErrors.UnexpectedResult); @@ -521,6 +518,68 @@ describe('DatabasePostgres', function () { }); }); // authenticationUpsert + describe('authenticationUpdateCredential', function () { + let identifier, credential; + beforeEach(function () { + identifier = 'username'; + }); + it('success', async function () { + const dbResult = { + rowCount: 1, + rows: undefined, + duration: 22, + }; + sinon.stub(db.db, 'result').resolves(dbResult); + await db.authenticationUpdateCredential(dbCtx, identifier, credential); + }); + it('failure', async function() { + credential = undefined; + const dbResult = { + rowCount: 0, + rows: undefined, + duration: 22, + }; + sinon.stub(db.db, 'result').resolves(dbResult); + try { + await db.authenticationUpdateCredential(dbCtx, identifier, credential); + assert.fail(noExpectedException); + } catch (e) { + assert(e instanceof DBErrors.UnexpectedResult); + } + }); + }); // authenticationUpdateCredential + + describe('authenticationUpdateOTPKey', function () { + let identifier, otpKey; + beforeEach(function () { + identifier = 'username'; + otpKey = '12345678901234567890123456789012'; + }); + it('success', async function () { + const dbResult = { + rowCount: 1, + rows: undefined, + duration: 22, + }; + sinon.stub(db.db, 'result').resolves(dbResult); + await db.authenticationUpdateOTPKey(dbCtx, identifier, otpKey); + }); + it('failure', async function() { + const dbResult = { + rowCount: 0, + rows: undefined, + duration: 22, + }; + sinon.stub(db.db, 'result').resolves(dbResult); + try { + await db.authenticationUpdateOTPKey(dbCtx, identifier, otpKey); + assert.fail(noExpectedException); + } catch (e) { + assert(e instanceof DBErrors.UnexpectedResult); + } + }); + }); // authenticationUpdateOTPKey + describe('subscriptionsByTopicId', function () { it('success', async function () { const expected = []; @@ -631,7 +690,7 @@ describe('DatabasePostgres', function () { const expected = new Error(); sinon.stub(db.db, 'manyOrNone').throws(expected); try { - await db.subscriptionDeliveryClaim(dbCtx, wanted, claimTimeoutSeconds, claimant ); + await db.subscriptionDeliveryClaim(dbCtx, wanted, claimTimeoutSeconds, claimant); assert.fail(noExpectedException); } catch (e) { assert.deepStrictEqual(e, expected); @@ -650,7 +709,7 @@ describe('DatabasePostgres', function () { changes: 1, lastInsertRowid: 'c2e254c5-aa6e-4a8f-b1a1-e474b07392bb', duration: 11, - } + }; sinon.stub(db.db, 'result').resolves(dbResult); const result = await db.subscriptionDeliveryClaimById(dbCtx, subscriptionId, claimTimeoutSeconds, claimant); assert.deepStrictEqual(result, expected); @@ -1026,7 +1085,7 @@ describe('DatabasePostgres', function () { rowCount: 1, rows: [], duration: 10, - } + }; const expected = { changes: 1, lastInsertRowid: undefined, @@ -1048,7 +1107,7 @@ describe('DatabasePostgres', function () { rowCount: 1, rows: [], duration: 10, - } + }; const expected = { changes: 1, lastInsertRowid: undefined, @@ -1070,7 +1129,7 @@ describe('DatabasePostgres', function () { rowCount: 0, rows: [], duration: 10, - } + }; sinon.stub(db.db, 'one').resolves(dbOne); sinon.stub(db.db, 'result').onCall(0).resolves(dbResult0).onCall(1).resolves(dbResult1); try { @@ -1091,7 +1150,7 @@ describe('DatabasePostgres', function () { rowCount: 0, rows: [], duration: 10, - } + }; sinon.stub(db.db, 'one').resolves(dbOne); sinon.stub(db.db, 'result').onCall(0).resolves(dbResult0).onCall(1).resolves(dbResult1); try { @@ -1193,11 +1252,17 @@ describe('DatabasePostgres', function () { describe('topicGetByUrl', function () { it('success', async function() { - const expected = []; + const expected = { id: topicId }; sinon.stub(db.db, 'oneOrNone').resolves(expected); const result = await db.topicGetByUrl(dbCtx, topicUrl); assert.deepStrictEqual(result, expected); }); + it('success, no default', async function() { + const expected = { id: topicId }; + sinon.stub(db.db, 'oneOrNone').resolves(expected); + const result = await db.topicGetByUrl(dbCtx, topicUrl, false); + assert.deepStrictEqual(result, expected); + }); it('failure', async function () { const expected = new Error(); sinon.stub(db.db, 'oneOrNone').throws(expected); @@ -1764,7 +1829,7 @@ describe('DatabasePostgres', function () { rowCount: 0, rows: [], duration: 10, - } + }; sinon.stub(db.db, 'result').resolves(dbResult); try { await db.verificationUpdate(dbCtx, verificationId, data); @@ -1790,7 +1855,7 @@ describe('DatabasePostgres', function () { rowCount: 1, rows: [], duration: 10, - } + }; sinon.stub(db.db, 'result').resolves(dbResult); await db.verificationValidated(dbCtx, verificationId); }); @@ -1799,7 +1864,7 @@ describe('DatabasePostgres', function () { rowCount: 0, rows: [], duration: 10, - } + }; sinon.stub(db.db, 'result').resolves(dbResult); try { await db.verificationValidated(dbCtx, verificationId); diff --git a/test/src/db/schema-version-helper.js b/test/src/db/schema-version-helper.js index b69735e..7e44f9b 100644 --- a/test/src/db/schema-version-helper.js +++ b/test/src/db/schema-version-helper.js @@ -1,8 +1,8 @@ /* eslint-env mocha */ 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const assert = require('node:assert'); +const sinon = require('sinon'); const fs = require('fs'); const svh = require('../../../src/db/schema-version-helper'); @@ -121,6 +121,7 @@ describe('SchemaVersionHelper', function () { .onCall(i++).returns(notDir) // 'init.sql' .onCall(i++).returns(isDir).onCall(i++).returns(isMig) // '1.0.1' .onCall(i++).returns(isDir).onCall(i++).returns(isMig) // '1.0.0' + ; const result = svh.allSchemaVersions('path'); assert.deepStrictEqual(result, expected); }); @@ -137,7 +138,7 @@ describe('SchemaVersionHelper', function () { max: { major: 1, minor: 1, patch: 1 }, }; current = { major: 1, minor: 0, patch: 1 }; - }); + }); it('covers', function () { const expected = ['1.1.0', '1.1.1']; fs.readdirSync.returns(['1.1.2', 'file.txt', '1.1.0', '1.1.1', 'init.sql', '1.0.1', '1.0.0']); @@ -151,6 +152,7 @@ describe('SchemaVersionHelper', function () { .onCall(i++).returns(notDir) // 'init.sql' .onCall(i++).returns(isDir).onCall(i++).returns(isMig) // '1.0.1' .onCall(i++).returns(isDir).onCall(i++).returns(isMig) // '1.0.0' + ; const result = svh.unappliedSchemaVersions('path', current, supported); assert.deepStrictEqual(result, expected); }); diff --git a/test/src/db/sqlite.js b/test/src/db/sqlite.js index deb0ee2..33f0028 100644 --- a/test/src/db/sqlite.js +++ b/test/src/db/sqlite.js @@ -1,12 +1,8 @@ -/* eslint-disable sonarjs/no-identical-functions */ -/* eslint-env mocha */ -/* eslint-disable sonarjs/no-duplicate-string */ 'use strict'; /* This provides implementation coverage, stubbing parts of better-sqlite3. */ -const assert = require('assert'); -// eslint-disable-next-line node/no-unpublished-require +const assert = require('node:assert'); const sinon = require('sinon'); const DBStub = require('../../stub-db'); const stubLogger = require('../../stub-logger'); @@ -47,6 +43,12 @@ describe('DatabaseSQLite', function () { sinon.restore(); }); + it('covers options', function () { + const xoptions = new Config('test'); + delete xoptions.db.connectionString; + db = new DB(stubLogger, xoptions); + }); + // Ensure all interface methods are implemented describe('Implementation', function () { it('implements interface', async function () { @@ -237,7 +239,7 @@ describe('DatabaseSQLite', function () { contentFetchNextAttempt: now, contentUpdated: now, url: topic.url, - } + }; const result = DB._topicDataToNative(topic); assert.deepStrictEqual(result, expected); }); @@ -341,10 +343,11 @@ describe('DatabaseSQLite', function () { }); // authenticationGet describe('authenticationUpsert', function () { - let identifier, credential; + let identifier, credential, otpKey; beforeEach(function () { identifier = 'username'; credential = '$z$foo'; + otpKey = '12345678901234567890123456789012'; }); it('success', async function() { const dbResult = { @@ -352,7 +355,7 @@ describe('DatabaseSQLite', function () { lastInsertRowid: undefined, }; sinon.stub(db.statement.authenticationUpsert, 'run').returns(dbResult); - await db.authenticationUpsert(dbCtx, identifier, credential); + await db.authenticationUpsert(dbCtx, identifier, credential, otpKey); }); it('failure', async function () { const dbResult = { @@ -361,7 +364,65 @@ describe('DatabaseSQLite', function () { }; sinon.stub(db.statement.authenticationUpsert, 'run').returns(dbResult); try { - await db.authenticationUpsert(dbCtx, identifier, credential); + await db.authenticationUpsert(dbCtx, identifier, credential, otpKey); + assert.fail(noExpectedException); + } catch (e) { + assert(e instanceof DBErrors.UnexpectedResult); + } + }); + }); // authenticationUpsert + + describe('authenticationUpdateCredential', function () { + let identifier, credential; + beforeEach(function () { + identifier = 'username'; + credential = '$z$foo'; + }); + it('success', async function() { + const dbResult = { + changes: 1, + lastInsertRowid: undefined, + }; + sinon.stub(db.statement.authenticationUpdateCredential, 'run').returns(dbResult); + await db.authenticationUpdateCredential(dbCtx, identifier, credential); + }); + it('failure', async function () { + const dbResult = { + changes: 0, + lastInsertRowid: undefined, + }; + sinon.stub(db.statement.authenticationUpdateCredential, 'run').returns(dbResult); + try { + await db.authenticationUpdateCredential(dbCtx, identifier, credential); + assert.fail(noExpectedException); + } catch (e) { + assert(e instanceof DBErrors.UnexpectedResult); + } + }); + }); // authenticationUpdateCredential + + describe('authenticationUpdateOTPKey', function () { + let identifier, otpKey; + beforeEach(function () { + identifier = 'username'; + otpKey = '12345678901234567890123456789012'; + }); + it('success', async function() { + const dbResult = { + changes: 1, + lastInsertRowid: undefined, + }; + sinon.stub(db.statement.authenticationUpdateOtpKey, 'run').returns(dbResult); + await db.authenticationUpdateOTPKey(dbCtx, identifier, otpKey); + }); + it('failure', async function () { + const dbResult = { + changes: 0, + lastInsertRowid: undefined, + }; + sinon.stub(db.statement.authenticationUpdateOtpKey, 'run').returns(dbResult); + try { + await db.authenticationUpdateOTPKey(dbCtx, identifier, otpKey); assert.fail(noExpectedException); } catch (e) { assert(e instanceof DBErrors.UnexpectedResult); @@ -881,7 +942,7 @@ describe('DatabaseSQLite', function () { const dbResult1 = { changes: 1, lastInsertRowid: undefined, - } + }; const expected = { changes: 1, lastInsertRowid: undefined, @@ -901,7 +962,7 @@ describe('DatabaseSQLite', function () { const dbResult1 = { changes: 1, lastInsertRowid: undefined, - } + }; const expected = { changes: 1, lastInsertRowid: undefined, @@ -921,7 +982,7 @@ describe('DatabaseSQLite', function () { const dbResult1 = { changes: 0, lastInsertRowid: undefined, - } + }; sinon.stub(db.statement.topicAttempts, 'get').returns(dbGet); sinon.stub(db.statement.topicAttemptsIncrement, 'run').returns(dbResult0); sinon.stub(db.statement.topicContentFetchDone, 'run').returns(dbResult1); @@ -941,7 +1002,7 @@ describe('DatabaseSQLite', function () { const dbResult1 = { changes: 0, lastInsertRowid: undefined, - } + }; sinon.stub(db.statement.topicAttempts, 'get').returns(dbGet); sinon.stub(db.statement.topicAttemptsIncrement, 'run').returns(dbResult0); sinon.stub(db.statement.topicContentFetchDone, 'run').returns(dbResult1); @@ -1046,6 +1107,12 @@ describe('DatabaseSQLite', function () { const result = await db.topicGetByUrl(dbCtx, topicUrl); assert.deepStrictEqual(result, expected); }); + it('success, no defaults', async function() { + const expected = []; + sinon.stub(db.statement.topicGetByUrl, 'get').returns(expected); + const result = await db.topicGetByUrl(dbCtx, topicUrl, false); + assert.deepStrictEqual(result, expected); + }); it('failure', async function () { const expected = new Error(); sinon.stub(db.statement.topicGetByUrl, 'get').throws(expected); @@ -1534,7 +1601,7 @@ describe('DatabaseSQLite', function () { DB._verificationDataToEngine(data); assert.strictEqual(data.isPublisherValidated, 0); }); - }) // _verificationDataToEngine + }); // _verificationDataToEngine describe('verificationInsert', function () { let verification; @@ -1625,7 +1692,7 @@ describe('DatabaseSQLite', function () { const dbResult = { changes: 0, lastInsertRowid: undefined, - } + }; sinon.stub(db.statement.verificationUpdate, 'run').returns(dbResult); try { await db.verificationUpdate(dbCtx, verificationId, data); @@ -1650,7 +1717,7 @@ describe('DatabaseSQLite', function () { const dbResult = { changes: 1, lastInsertRowid: undefined, - } + }; sinon.stub(db.statement.verificationValidate, 'run').returns(dbResult); await db.verificationValidated(dbCtx, verificationId); }); @@ -1658,7 +1725,7 @@ describe('DatabaseSQLite', function () { const dbResult = { changes: 0, lastInsertRowid: undefined, - } + }; sinon.stub(db.statement.verificationValidate, 'run').returns(dbResult); try { await db.verificationValidated(dbCtx, verificationId); diff --git a/test/src/link-helper.js b/test/src/link-helper.js index 1f91493..5f84362 100644 --- a/test/src/link-helper.js +++ b/test/src/link-helper.js @@ -1,8 +1,7 @@ -/* eslint-env mocha */ 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const assert = require('node:assert'); +const sinon = require('sinon'); const LinkHelper = require('../../src/link-helper'); const stubLogger = require('../stub-logger'); const testData = require('../test-data/link-helper'); diff --git a/test/src/logger.js b/test/src/logger.js index 47017dd..1e1faf3 100644 --- a/test/src/logger.js +++ b/test/src/logger.js @@ -1,8 +1,7 @@ -/* eslint-env mocha */ 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const assert = require('node:assert'); +const sinon = require('sinon'); const Logger = require('../../src/logger'); const Config = require('../../config'); diff --git a/test/src/manager.js b/test/src/manager.js index 9d8c380..ed057c4 100644 --- a/test/src/manager.js +++ b/test/src/manager.js @@ -1,10 +1,7 @@ -/* eslint-env mocha */ -/* eslint-disable capitalized-comments, sonarjs/no-duplicate-string, sonarjs/no-identical-functions */ - 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const assert = require('node:assert'); +const sinon = require('sinon'); const Manager = require('../../src/manager'); const Config = require('../../config'); @@ -398,7 +395,7 @@ describe('Manager', function () { describe('_getRootData', function () { it('extracts expected values', function () { req.getHeader.returns('user@example.com'); - ctx = Object.assign({}, testData.validSubscribeCtx) + ctx = Object.assign({}, testData.validSubscribeCtx); const result = Manager._getRootData(req, ctx); assert.deepStrictEqual(result, testData.validRootData); }); @@ -791,7 +788,7 @@ describe('Manager', function () { assert(manager.db.topicFetchRequested.called); assert.strictEqual(res.statusCode, 202); assert(res.end.called); - assert(manager.communication.topicFetchClaimAndProcessById.called) + assert(manager.communication.topicFetchClaimAndProcessById.called); }); it('covers no immediate processing', async function() { manager.options.manager.processImmediately = false; @@ -803,7 +800,7 @@ describe('Manager', function () { assert(manager.db.topicFetchRequested.called); assert.strictEqual(res.statusCode, 202); assert(res.end.called); - assert(!manager.communication.topicFetchClaimAndProcessById.called) + assert(!manager.communication.topicFetchClaimAndProcessById.called); }); }); // _publishRequest diff --git a/test/src/service.js b/test/src/service.js index 62c0059..2cfe38d 100644 --- a/test/src/service.js +++ b/test/src/service.js @@ -1,24 +1,24 @@ -/* eslint-env mocha */ -/* eslint-disable capitalized-comments */ - 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const assert = require('node:assert'); +const sinon = require('sinon'); const stubDb = require('../stub-db'); const stubLogger = require('../stub-logger'); const Service = require('../../src/service'); const Config = require('../../config'); +const { AsyncLocalStorage } = require('node:async_hooks'); describe('Service', function () { - let service, options; + let service, options, asyncLocalStorage; let req, res, ctx; beforeEach(function () { + asyncLocalStorage = new AsyncLocalStorage(); options = new Config('test'); - service = new Service(stubLogger, stubDb, options); + service = new Service(stubLogger, stubDb, options, asyncLocalStorage); + stubLogger._reset(); sinon.stub(service.manager); sinon.stub(service.sessionManager); sinon.stub(service.authenticator); @@ -46,6 +46,23 @@ describe('Service', function () { assert(service); }); + describe('preHandler', function () { + it('logs requestId', async function () { + sinon.stub(service.__proto__.__proto__, 'preHandler').resolves(); + await service.asyncLocalStorage.run({}, async () => { + await service.preHandler(req, res, ctx); + const logObject = service.asyncLocalStorage.getStore(); + assert('requestId' in logObject); + }); + }); + it('covers weird async context failure', async function () { + sinon.stub(service.__proto__.__proto__, 'preHandler').resolves(); + sinon.stub(service.asyncLocalStorage, 'getStore').returns(); + await service.preHandler(req, res, ctx); + assert(service.logger.debug.called); + }); + }); // preHandler + describe('maybeIngestBody', function () { beforeEach(function () { sinon.stub(service, 'bodyData'); @@ -171,6 +188,34 @@ describe('Service', function () { }); }); // handlerGetAdminLogin + describe('handlerGetAdminSettings', function () { + it('covers logged in', async function () { + service.authenticator.sessionRequiredLocal.resolves(true); + await service.handlerGetAdminSettings(req, res, ctx); + assert(service.sessionManager.getAdminSettings.called); + }); + it('covers not logged in', async function () { + service.authenticator.sessionRequiredLocal.resolves(false); + await service.handlerGetAdminSettings(req, res, ctx); + assert(service.sessionManager.getAdminSettings.notCalled); + }); + }); // handlerGetAdminSettings + + describe('handlerPostAdminSettings', function () { + it('covers logged in', async function () { + service.authenticator.sessionRequiredLocal.resolves(true); + sinon.stub(service, 'bodyData').resolves(); + await service.handlerPostAdminSettings(req, res, ctx); + assert(service.sessionManager.postAdminSettings.called); + }); + it('covers logged outo', async function () { + service.authenticator.sessionRequiredLocal.resolves(false); + sinon.stub(service, 'bodyData').resolves(); + await service.handlerPostAdminSettings(req, res, ctx); + assert(service.sessionManager.postAdminSettings.notCalled); + }); + }); // handlerPostAdminSettings + describe('handlerPostAdminLogin', function () { it('covers', async function () { sinon.stub(service, 'bodyData').resolves(); @@ -184,7 +229,7 @@ describe('Service', function () { await service.handlerGetAdminLogout(req, res, ctx); assert(service.sessionManager.getAdminLogout.called); }); -}); // handlerGetAdminLogout + }); // handlerGetAdminLogout describe('handlerGetAdminIA', function () { it('covers', async function () { diff --git a/test/src/template/admin-overview-html.js b/test/src/template/admin-overview-html.js index 1e715d2..1f99782 100644 --- a/test/src/template/admin-overview-html.js +++ b/test/src/template/admin-overview-html.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict'; -const assert = require('assert'); +const assert = require('node:assert'); const template = require('../../../src/template/admin-overview-html'); const Config = require('../../../config'); const lintHtml = require('../../lint-html'); @@ -14,21 +14,21 @@ describe('Admin Overview HTML Template', function () { config = new Config('test'); }); - it('covers missing topics', function () { + it('covers missing topics', async function () { const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); - it('covers single topic', function () { + it('covers single topic', async function () { ctx.topics = [{}]; const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); - it('covers plural topics', function () { + it('covers plural topics', async function () { ctx.topics = [{}, {}, {}]; const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); }); diff --git a/test/src/template/admin-topic-details-html.js b/test/src/template/admin-topic-details-html.js index 7795c2b..ce19af7 100644 --- a/test/src/template/admin-topic-details-html.js +++ b/test/src/template/admin-topic-details-html.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict'; -const assert = require('assert'); +const assert = require('node:assert'); const template = require('../../../src/template/admin-topic-details-html'); const Config = require('../../../config'); const lintHtml = require('../../lint-html'); @@ -22,28 +22,28 @@ describe('Admin Topic Details HTML Template', function () { config = new Config('test'); }); - it('renders', function () { + it('renders', async function () { const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); - it('covers null topic', function () { + it('covers null topic', async function () { ctx.topic = null; ctx.subscriptions = null; const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); - it('covers missing subscriptions', function () { + it('covers missing subscriptions', async function () { delete ctx.subscriptions; const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); - it('covers plural subscriptions', function () { + it('covers plural subscriptions', async function () { ctx.subscriptions = [{}, {}, {}]; const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); }); diff --git a/test/src/template/badge-svg.js b/test/src/template/badge-svg.js index 1f4e026..94c6f4a 100644 --- a/test/src/template/badge-svg.js +++ b/test/src/template/badge-svg.js @@ -1,9 +1,8 @@ /* eslint-env mocha */ 'use strict'; -const assert = require('assert'); +const assert = require('node:assert'); const template = require('../../../src/template/badge-svg'); -const Config = require('../../../config'); describe('Badge SVG Template', function () { let ctx, label, message, accessibleText; diff --git a/test/src/template/histogram-svg.js b/test/src/template/histogram-svg.js index 656ccdb..4971921 100644 --- a/test/src/template/histogram-svg.js +++ b/test/src/template/histogram-svg.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict'; -const assert = require('assert'); +const assert = require('node:assert'); const template = require('../../../src/template/histogram-svg'); describe('Histogram SVG Template', function () { diff --git a/test/src/template/root-html.js b/test/src/template/root-html.js index 36c7b44..6e1458f 100644 --- a/test/src/template/root-html.js +++ b/test/src/template/root-html.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict'; -const assert = require('assert'); +const assert = require('node:assert'); const template = require('../../../src/template/root-html'); const Config = require('../../../config'); const lintHtml = require('../../lint-html'); @@ -14,24 +14,24 @@ describe('Root HTML Template', function () { config = new Config('test'); }); - it('renders', function () { + it('renders', async function () { const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); - it('covers options', function () { + it('covers options', async function () { delete config.dingus.selfBaseUrl; const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); - it('covers options', function () { + it('covers options', async function () { config.adminContactHTML = '
support
'; config.manager.publicHub = false; const result = template(ctx, config); - lintHtml(result); + await lintHtml(result); assert(result); }); diff --git a/test/src/template/template-helper.js b/test/src/template/template-helper.js index 5a62a7c..6dc85a3 100644 --- a/test/src/template/template-helper.js +++ b/test/src/template/template-helper.js @@ -1,7 +1,7 @@ /* eslint-env mocha */ 'use strict'; -const assert = require('assert'); +const assert = require('node:assert'); const th = require('../../../src/template/template-helper'); describe('Template Helper', function () { diff --git a/test/src/worker.js b/test/src/worker.js index 5c97c0b..7f99de1 100644 --- a/test/src/worker.js +++ b/test/src/worker.js @@ -1,8 +1,7 @@ -/* eslint-env mocha */ 'use strict'; -const assert = require('assert'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const assert = require('node:assert'); +const sinon = require('sinon'); const Worker = require('../../src/worker'); const Config = require('../../config'); @@ -131,6 +130,12 @@ describe('Worker', function () { stubCtx = {}; }); it('gets tasks', async function () { + /** + * In older versions, could just deepStrictEqual un-awaited promises for equality, + * but post 14 or so, async_id symbol properties are included in comparison, and + * in some executions of test suites these are somehow different in value so the test + * was failing. So now we settle everything prior to comparison. + */ const expected = [ Promise.resolve('first'), Promise.reject('bad'), @@ -138,7 +143,11 @@ describe('Worker', function () { ]; worker.promiseGiver.resolves(expected); const result = await worker._getWork(stubCtx); - assert.deepStrictEqual(result, expected); + + const expectedResolved = await Promise.allSettled(expected); + const resultResolved = await Promise.allSettled(result); + assert.deepStrictEqual(resultResolved, expectedResolved); + assert.strictEqual(worker.inFlight.length, expected.length); }); it('covers none wanted', async function () { diff --git a/test/stub-db.js b/test/stub-db.js index 8ef1045..129c907 100644 --- a/test/stub-db.js +++ b/test/stub-db.js @@ -1,7 +1,7 @@ /* eslint-disable security/detect-object-injection */ 'use strict'; -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const sinon = require('sinon'); const spyFns = [ 'context', @@ -12,6 +12,8 @@ const stubFns = [ 'authenticationSuccess', 'authenticationGet', 'authenticationUpsert', + 'authenticationUpdateCredential', + 'authenticationUpdateOTPKey', 'healthCheck', 'initialize', 'subscriptionsByTopicId', diff --git a/test/stub-logger.js b/test/stub-logger.js index 6085928..8c10ebd 100644 --- a/test/stub-logger.js +++ b/test/stub-logger.js @@ -1,6 +1,6 @@ 'use strict'; -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const sinon = require('sinon'); const nop = () => { /* */ }; const stubLogger = process.env.VERBOSE_TESTS ? console : {