From: Justin Wind Date: Sat, 22 Jun 2024 22:21:18 +0000 (-0700) Subject: fix changelog X-Git-Url: https://git.squeep.com/?a=commitdiff_plain;ds=sidebyside;h=HEAD;hp=ae232753929a41b380d3e147db581b0622723dfa;p=squeep-indie-auther fix changelog --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f7a8ae..9791966 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,12 @@ Releases and notable changes to this project are documented here. -## [v1.2.0] - TBD +## [unreleased] - TBD + +## [v1.2.0] - 2024-06-22 - Add UI for changing password, supporting OTP for auth +- Updated dependencies. ## [v1.1.0] - 2023-12-23 @@ -36,7 +39,8 @@ Releases and notable changes to this project are documented here. --- -[Unreleased]: https://git.squeep.com/?p=squeep-indie-auther;a=commitdiff;h=HEAD;hp=v1.1.0 +[Unreleased]: https://git.squeep.com/?p=squeep-indie-auther;a=commitdiff;h=HEAD;hp=v1.2.0 +[v1.2.0]: https://git.squeep.com/?p=squeep-indie-auther;a=commitdiff;h=v1.2.0;hp=v1.1.0 [v1.1.0]: https://git.squeep.com/?p=squeep-indie-auther;a=commitdiff;h=v1.1.0;hp=v1.0.3 [v1.0.3]: https://git.squeep.com/?p=squeep-indie-auther;a=commitdiff;h=v1.0.3;hp=v1.0.2 [v1.0.2]: https://git.squeep.com/?p=squeep-indie-auther;a=commitdiff;h=v1.0.2;hp=v1.0.1 diff --git a/eslint.config.js b/eslint.config.js index e02ca72..fcda56f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,111 +1,7 @@ 'use strict'; -const globals = require('globals'); -const js = require('@eslint/js'); -const node = require('eslint-plugin-n'); -const security = require('eslint-plugin-security'); -const sonarjs = require('eslint-plugin-sonarjs'); -const { FlatCompat } = require('@eslint/eslintrc'); -const compat = new FlatCompat(); +const squeepConfig = require('@squeep/eslint-config'); module.exports = [ - js.configs.recommended, - ...compat.config(node.configs.recommended), - security.configs.recommended, - ...compat.config(sonarjs.configs.recommended), - { - files: [ '**/*.js' ], - plugins: { - node, - security, - sonarjs, - }, - languageOptions: { - ecmaVersion: 2023, - sourceType: 'script', - }, - rules: { - 'array-element-newline': [ - 'error', - 'consistent', - ], - 'arrow-parens': [ - 'error', - 'always', - ], - 'arrow-spacing': [ - 'error', - { - 'after': true, - 'before': true, - }, - ], - 'block-scoped-var': 'error', - 'block-spacing': 'error', - 'brace-style': 'error', - 'callback-return': 'error', - 'camelcase': 'error', - 'class-methods-use-this': 'error', - 'comma-dangle': [ - 'error', - 'always-multiline', - ], - 'comma-spacing': [ - 'error', - { - 'after': true, - 'before': false, - }, - ], - 'comma-style': [ - 'error', - 'last', - ], - 'indent': [ - 'warn', - 2, - { - 'SwitchCase': 1, - }, - ], - 'sonarjs/cognitive-complexity': 'warn', - 'sonarjs/no-duplicate-string': 'warn', - 'keyword-spacing': 'error', - 'linebreak-style': [ - 'error', - 'unix', - ], - 'no-unused-vars': [ - 'error', { - 'varsIgnorePattern': '^_', - }, - ], - 'object-curly-spacing': [ - 'error', - 'always', - ], - 'prefer-const': 'error', - 'quotes': [ - 'error', - 'single', - ], - 'semi': [ - 'error', - 'always', - ], - 'strict': 'error', - 'vars-on-top': 'error', - }, - }, - { - files: ['test/**'], - languageOptions: { - globals: { - ...globals.mocha, - }, - }, - rules: { - "n/no-unpublished-require": "off", - }, - }, + ...squeepConfig, ]; diff --git a/package-lock.json b/package-lock.json index b28df97..9cc8c45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,54 +1,41 @@ { "name": "@squeep/indie-auther", - "version": "1.1.0", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@squeep/indie-auther", - "version": "1.1.0", + "version": "1.2.0", "license": "ISC", "dependencies": { - "@squeep/amqp-helper": "git+https://git.squeep.com/squeep-amqp-helper#v1.0.0", - "@squeep/api-dingus": "^2.1.0", - "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.4.0", - "@squeep/chores": "git+https://git.squeep.com/squeep-chores/#v1.0.1", - "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.6.0", - "@squeep/indieauth-helper": "^1.4.1", - "@squeep/logger-json-console": "^3.0.2", - "@squeep/mystery-box": "^2.0.2", - "@squeep/resource-authentication-module": "git+https://git.squeep.com/squeep-resource-authentication-module#v1.0.1", - "@squeep/roman": "^1.0.1", - "@squeep/web-linking": "^1.0.8", - "better-sqlite3": "^9.4.5", - "pg-promise": "^11.6.0", - "uuid": "^9.0.1" + "@squeep/amqp-helper": "git+https://git.squeep.com/squeep-amqp-helper#v1.0.1", + "@squeep/api-dingus": "^2", + "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.5.0", + "@squeep/chores": "git+https://git.squeep.com/squeep-chores/#v1.0.2", + "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.6.1", + "@squeep/indieauth-helper": "^1.4", + "@squeep/logger-json-console": "^3", + "@squeep/mystery-box": "^2", + "@squeep/roman": "^1", + "@squeep/web-linking": "^1", + "better-sqlite3": "^11", + "pg-promise": "^11", + "uuid": "^10" }, "devDependencies": { - "@squeep/test-helper": "git+https://git.squeep.com/squeep-test-helper#v1.0.1", - "eslint": "^8.57.0", - "eslint-plugin-n": "^16.6.2", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-security": "^2.1.1", - "eslint-plugin-sonarjs": "^0.25.1", - "html-validate": "^8.18.1", - "mocha": "^10.4.0", - "mocha-steps": "^1.3.0", - "nyc": "^15.1.0", - "pre-commit": "^1.2.2", - "sinon": "^17.0.1" + "@squeep/eslint-config": "^1", + "@squeep/test-helper": "git+https://git.squeep.com/squeep-test-helper#v2.0.0", + "eslint": "^9", + "html-validate": "^8", + "mocha": "^10", + "mocha-steps": "^1", + "nyc": "^17", + "pre-commit": "^1", + "sinon": "^18" }, "engines": { - "node": "^14 >=14.18 || >=15.7" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=20" } }, "node_modules/@acuminous/bitsyntax": { @@ -78,12 +65,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "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.24.2", + "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" }, "engines": { @@ -91,30 +78,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "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.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "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.24.2", - "@babel/generator": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.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", @@ -145,12 +132,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", - "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", + "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.24.0", + "@babel/types": "^7.24.7", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -160,13 +147,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "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.23.5", - "@babel/helper-validator-option": "^7.23.5", + "@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.1" @@ -185,62 +172,66 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "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.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "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.22.15", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "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.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "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.24.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "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.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@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" @@ -250,77 +241,77 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "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.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "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.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "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.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "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.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "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.24.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz", - "integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==", + "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.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "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.22.20", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" @@ -401,9 +392,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", - "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", + "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" @@ -413,33 +404,33 @@ } }, "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "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.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" + "@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.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.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" }, @@ -457,19 +448,36 @@ } }, "node_modules/@babel/types": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", - "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "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.23.4", - "@babel/helper-validator-identifier": "^7.22.20", + "@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.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -485,25 +493,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.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "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.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "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.6.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", @@ -511,19 +545,40 @@ "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.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "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/@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": { @@ -538,20 +593,6 @@ "node": ">= 16" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -565,11 +606,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "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", @@ -851,6 +899,11 @@ "node": ">=14" } }, + "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", @@ -868,11 +921,11 @@ } }, "node_modules/@sindresorhus/is": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", - "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-6.3.1.tgz", + "integrity": "sha512-FX4MfcifwJyFOI2lPoX7PQxCqx8BG1HCho7WdiXwpEQx1Ycij0JxkfYtGK7yqNScrZGSlt6RE6sw8QYoH7eKnQ==", "engines": { - "node": ">=14.16" + "node": ">=16" }, "funding": { "url": "https://github.com/sindresorhus/is?sponsor=1" @@ -923,185 +976,171 @@ "dev": true }, "node_modules/@squeep/amqp-helper": { - "version": "1.0.0", - "resolved": "git+https://git.squeep.com/squeep-amqp-helper#174280d3f44ba13dac0b26d42d968189a4f4fa93", - "license": "ISC", + "version": "1.0.1", + "resolved": "git+https://git.squeep.com/squeep-amqp-helper#35396c02cf64a98d0963b51101686893b92362b4", "dependencies": { - "amqplib": "^0.10.3" + "@squeep/log-helper": "^1", + "amqplib": "^0.10.4" }, "engines": { "node": ">=14" } }, "node_modules/@squeep/api-dingus": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@squeep/api-dingus/-/api-dingus-2.1.0.tgz", - "integrity": "sha512-SCLPHbSHTz5en5XO8IMyTLr6R+0jIDpL3dSxS3e4XLC3521LzorNywGteMdnZKhwXwahjf4XngxNzmO0kFp6Kw==", + "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.0.0", + "@squeep/log-helper": "^1", "mime-db": "^1.52.0", "uuid": "^9.0.1" }, "engines": { - "node": ">=14" + "node": ">=14.13.1" + } + }, + "node_modules/@squeep/api-dingus/node_modules/uuid": { + "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" } }, "node_modules/@squeep/authentication-module": { - "version": "1.4.0", - "resolved": "git+https://git.squeep.com/squeep-authentication-module/#9c604adfcde56e35767e3eba70890308ec2d3110", - "license": "ISC", + "version": "1.5.0", + "resolved": "git+https://git.squeep.com/squeep-authentication-module/#5ea2ffe571a74618eef073c58c5fef06e1cf06a7", "dependencies": { - "@squeep/api-dingus": "^2.1.0", - "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.6.0", - "@squeep/indieauth-helper": "^1.4.1", - "@squeep/mystery-box": "^2.0.2", - "@squeep/totp": "^1.1.4" + "@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": "^18" + "node": ">=18" }, "optionalDependencies": { "argon2": "^0.40.1", "node-linux-pam": "^0.2.1" } }, + "node_modules/@squeep/authentication-module/node_modules/uuid": { + "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" + } + }, "node_modules/@squeep/chores": { + "version": "1.0.2", + "resolved": "git+https://git.squeep.com/squeep-chores/#e429ea710c1d5a5839618a1151f4c0cff9326539", + "dependencies": { + "@squeep/log-helper": "^1" + } + }, + "node_modules/@squeep/eslint-config": { "version": "1.0.1", - "resolved": "git+https://git.squeep.com/squeep-chores/#a77e8814cbba0ad751e249850d1f7b144da6446b", - "license": "ISC", + "resolved": "https://registry.npmjs.org/@squeep/eslint-config/-/eslint-config-1.0.1.tgz", + "integrity": "sha512-LID0nJW/+Sk+7AKWM9gVEwk5O8NXvlo1+TApOOlZ4RZDaRqkH1EnEqxZcX/MKjuyRh8D5XEU0fn72MsiEjeEiA==", + "dev": true, "dependencies": { - "@squeep/log-helper": "^1.0.0" + "@eslint/js": "^9", + "eslint-plugin-jsdoc": "^48", + "eslint-plugin-n": "^17", + "eslint-plugin-security": "^3", + "eslint-plugin-sonarjs": "^1", + "globals": "^15" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "eslint": ">= 9" } }, "node_modules/@squeep/html-template-helper": { - "version": "1.6.0", - "resolved": "git+https://git.squeep.com/squeep-html-template-helper#2d0ba72a2ea35f45c1ab1ac81fce3d0cbe7db419", - "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.4.1", - "resolved": "https://registry.npmjs.org/@squeep/indieauth-helper/-/indieauth-helper-1.4.1.tgz", - "integrity": "sha512-x/yqrjrbp0vTdvIW8e9CKsr5+YwmDp/x4nK4H5LInt07rk4nthxv7e7qIgy97OFtvFnoNee+N9gyi3TzIIiGoQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@squeep/indieauth-helper/-/indieauth-helper-1.4.2.tgz", + "integrity": "sha512-PKOr2Mx8e1RwdJ6ab22gWAlbzktDNORIt4xzGZ0iXbvbTdqNLdpAKBHi8Il0vYgZU0HAO3utNqMX5grSfKaDrw==", "dependencies": { - "@squeep/log-helper": "^1.0.0", - "@squeep/web-linking": "^1.0.8", - "got": "^13.0.0", - "iconv": "^3.0.1", - "ip-address": "^9.0.5", - "microformats-parser": "^2.0.2" + "@squeep/log-helper": "^1", + "@squeep/web-linking": "^1", + "got": "^14", + "iconv": "^3", + "ip-address": "^9", + "microformats-parser": "^2" }, "engines": { - "node": "^14 >=14.18 || >=15.7" + "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.0", - "resolved": "https://registry.npmjs.org/@squeep/log-helper/-/log-helper-1.0.0.tgz", - "integrity": "sha512-i61ECZLWQI2rhkXj9pDzH1Md5ICghL9zvh5QFVo0BTayuSrdS9SWkJ6gV1qWki/Xz6SuE0y0y145NyHlvOuVaw==", + "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" + "node": ">=14.13.1" } }, "node_modules/@squeep/logger-json-console": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@squeep/logger-json-console/-/logger-json-console-3.0.2.tgz", - "integrity": "sha512-Qz2QMwhyyRB5sZFB/S6eUt7TnmKCPB6oUqa8SW2gGGOLTcvf+0nbFgqqzlFwtUEwF3KwCmMnOt7lwq5PLrm24Q==", + "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": ">=17" } }, "node_modules/@squeep/mystery-box": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@squeep/mystery-box/-/mystery-box-2.0.2.tgz", - "integrity": "sha512-YoVx9F/ZFOdgPrt5ey3Vg+ttK4nsnfeSjzVDBOCB1L5q2H1V2wZ4DV0/l7mkqPgHHojGeJqncGs/KhB6Lu916g==", + "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/resource-authentication-module": { - "version": "1.0.1", - "resolved": "git+https://git.squeep.com/squeep-resource-authentication-module#0dce6b122b90dc9d2fd3b7191cdef4d41e256ae3", - "license": "ISC", - "dependencies": { - "@squeep/api-dingus": "v2.0.0", - "uuid": "^9.0.0" - }, - "engines": { - "node": "^14 >=14.18 || >=15.7" - } - }, - "node_modules/@squeep/resource-authentication-module/node_modules/@squeep/api-dingus": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@squeep/api-dingus/-/api-dingus-2.0.0.tgz", - "integrity": "sha512-HKz/yB1KNmEcHB92KIvrNvwMph5fSdJBrxKSgERYfyQkLFl2vSwDV+IlFvi68DYmMBP3lWKzQcTXWBMYlW3c0g==", - "dependencies": { - "mime-db": "^1.52.0", - "uuid": "^9.0.0" - }, - "engines": { - "node": ">=14" - } - }, "node_modules/@squeep/roman": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@squeep/roman/-/roman-1.0.1.tgz", - "integrity": "sha512-mGh8duO0LQusXzGf4N4Um1T9CxKZBHe1i9QvvUCq8f3U2qipugufAUxolMLq3N56wvcD13RcI9R6swIxxIAS8Q==" + "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/test-helper": { - "version": "1.0.1", - "resolved": "git+https://git.squeep.com/squeep-test-helper#cc0f69b40de9ae3342f1b7a1784d37769e7f1e84", - "dev": true, - "license": "ISC", - "dependencies": { - "eslint": "^8.53.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-security": "^1.7.1", - "eslint-plugin-sonarjs": "^0.23.0", - "mocha": "^10.2.0", - "nyc": "^15.1.0", - "pre-commit": "^1.2.2", - "sinon": "^17.0.1" - } - }, - "node_modules/@squeep/test-helper/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==", - "dev": true, - "dependencies": { - "safe-regex": "^2.1.1" - } - }, - "node_modules/@squeep/test-helper/node_modules/eslint-plugin-sonarjs": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.23.0.tgz", - "integrity": "sha512-z44T3PBf9W7qQ/aR+NmofOTyg6HLhSEZOPD4zhStqBpLoMp8GYhFksuUBnCxbnf1nfISpKBVkQhiBLFI/F4Wlg==", - "dev": true, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" - } + "version": "2.0.0", + "resolved": "git+https://git.squeep.com/squeep-test-helper#196f3e6e722245fa19703ae0d6a57807184f3c94", + "dev": true }, "node_modules/@squeep/totp": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@squeep/totp/-/totp-1.1.4.tgz", - "integrity": "sha512-cMoicNB5xIDMdcOtTfkzWZ0eQCepatTsFoWXtQ8Ja4FfvAA3ZWwIMfKV4K7zbx1MjYGF/Ufikxa6CaPS6yd5mw==", + "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" @@ -1111,9 +1150,9 @@ } }, "node_modules/@squeep/web-linking": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@squeep/web-linking/-/web-linking-1.0.8.tgz", - "integrity": "sha512-+0nCl/IXY8RHBWNr5mJMkU+U62in9xYDigIMkMKBp0bWnah/gjXv3NxAa4+LkxCMZU0STt/uBjuVM7SpvuQHSg==", + "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" } @@ -1129,17 +1168,46 @@ "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/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "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", @@ -1147,9 +1215,9 @@ "optional": true }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "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" @@ -1209,9 +1277,9 @@ } }, "node_modules/amqplib": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.3.tgz", - "integrity": "sha512-UHmuSa7n8vVW/a5HGh2nFPqAEr8+cD4dEZ6u9GjP91nHfr1a54RyAKyra7Sb5NH7NBKOUlyQSMXIp0qAixKexw==", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.4.tgz", + "integrity": "sha512-DMZ4eCEjAVdX1II2TfIUpJhfKAuoCeDIo/YyETbfAqehHTXxxs7WOOd+N1Xxr4cKhx12y23zk8/os98FxlZHrw==", "dependencies": { "@acuminous/bitsyntax": "^0.1.2", "buffer-more-ints": "~1.0.0", @@ -1292,10 +1360,20 @@ "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, + "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": ">=14" + } + }, "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": { "delegates": "^1.0.0", @@ -1333,14 +1411,14 @@ } }, "node_modules/argon2": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.40.1.tgz", - "integrity": "sha512-DjtHDwd7pm12qeWyfihHoM8Bn5vGcgH6sKwgPqwNYroRmxlrzadHEvMyuvQxN/V8YSyRRKD5x6ito09q1e9OyA==", + "version": "0.40.3", + "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.40.3.tgz", + "integrity": "sha512-FrSmz4VeM91jwFvvjsQv9GYp6o/kARWoYKjbjDB2U5io1H3e5X67PYGclFDeQff6UXIhUd4aHR3mxCdBbMMuQw==", "hasInstallScript": true, "optional": true, "dependencies": { "@phc/format": "^1.0.0", - "node-addon-api": "^7.1.0", + "node-addon-api": "^8.0.0", "node-gyp-build": "^4.8.0" }, "engines": { @@ -1395,9 +1473,9 @@ ] }, "node_modules/better-sqlite3": { - "version": "9.4.5", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.4.5.tgz", - "integrity": "sha512-uFVyoyZR9BNcjSca+cp3MWCv6upAv+tbMC4SWM51NIMhoQOm4tjIkyxFO/ZsYdGAF61WJBgdzyJcz4OokJi0gQ==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.0.0.tgz", + "integrity": "sha512-1NnNhmT3EZTsKtofJlMox1jkMxdedILury74PwUbQBjWgo4tL4kf7uTAjU55mgQwjdzqakSTjkf+E1imrFwjnA==", "hasInstallScript": true, "dependencies": { "bindings": "^1.5.0", @@ -1485,12 +1563,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" @@ -1503,9 +1581,9 @@ "dev": true }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "dev": true, "funding": [ { @@ -1522,10 +1600,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -1568,27 +1646,6 @@ "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "dependencies": { - "semver": "^7.0.0" - } - }, "node_modules/cacheable-lookup": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", @@ -1598,20 +1655,46 @@ } }, "node_modules/cacheable-request": { - "version": "10.2.14", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", - "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "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.2", - "get-stream": "^6.0.1", + "@types/http-cache-semantics": "^4.0.4", + "get-stream": "^9.0.1", "http-cache-semantics": "^4.1.1", - "keyv": "^4.5.3", + "keyv": "^4.5.4", "mimic-response": "^4.0.0", - "normalize-url": "^8.0.0", + "normalize-url": "^8.0.1", "responselike": "^3.0.0" }, "engines": { - "node": ">=14.16" + "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": { @@ -1648,9 +1731,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001606", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz", - "integrity": "sha512-LPbwnW4vfpJId225pwjZJOgX1m9sGfbw/RKJvw/t0QhYOOaTXHvkjVGFGPpvwEzufrjvTlsULnVTxdy4/6cqkg==", + "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": [ { @@ -1815,6 +1898,15 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "devOptional": true }, + "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": ">= 12.0.0" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -2026,18 +2118,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/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2045,9 +2125,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.729", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.729.tgz", - "integrity": "sha512-bx7+5Saea/qu14kmPTDHQxkp2UnziG3iajUQu3BxFvCOnpAJdDbMV4rSl+EqFDkkpNNVUFlR1kDfpL59xfy1HA==", + "version": "1.4.810", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.810.tgz", + "integrity": "sha512-Kaxhu4T7SJGpRQx99tq216gCq2nMxJo+uuT6uzz9l8TVN2stL7M06MIIXAtr9jsrLs2Glflgf2vMQRepxawOdQ==", "dev": true }, "node_modules/emoji-regex": { @@ -2064,6 +2144,19 @@ "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.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -2103,41 +2196,37 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "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.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@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", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "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", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -2151,16 +2240,16 @@ "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-compat-utils": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.0.tgz", - "integrity": "sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==", + "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": { "semver": "^7.5.4" @@ -2172,199 +2261,165 @@ "eslint": ">=6.0.0" } }, - "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-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-utils": "^2.0.0", - "regexpp": "^3.0.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" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "eslint": ">=4.19.1" + "eslint": ">=8" } }, - "node_modules/eslint-plugin-es-x": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.6.0.tgz", - "integrity": "sha512-I0AmeNgevgaTR7y2lrVCJmGYF0rjoznpDvqV/kIkZSZbZ8Rw3eu4cGlvBBULScfkSOCzqKbff5LR4CNrV7mZHA==", + "node_modules/eslint-plugin-jsdoc": { + "version": "48.2.13", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.13.tgz", + "integrity": "sha512-4MzMKN0uMIehmFUVzJxNmjc573HnTKLt7Qrg7QQyXC3JkHBweaVbHwgwG+T3boefD3NyLXRHNOYYPJqmslDvHA==", "dev": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.6.0", - "eslint-compat-utils": "^0.5.0" + "@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": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" + "node": ">=18" }, "peerDependencies": { - "eslint": ">=8" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-plugin-n": { - "version": "16.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", - "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", + "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", - "builtins": "^5.0.1", + "enhanced-resolve": "^5.17.0", "eslint-plugin-es-x": "^7.5.0", "get-tsconfig": "^4.7.0", - "globals": "^13.24.0", + "globals": "^15.0.0", "ignore": "^5.2.4", - "is-builtin-module": "^3.2.1", - "is-core-module": "^2.12.1", - "minimatch": "^3.1.2", - "resolve": "^1.22.2", + "minimatch": "^9.0.0", "semver": "^7.5.3" }, "engines": { - "node": ">=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://opencollective.com/eslint" }, "peerDependencies": { - "eslint": ">=7.0.0" + "eslint": ">=8.23.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-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": { - "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" - }, - "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "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" + "balanced-match": "^1.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/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": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=16 || 14 >=14.17" }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/eslint-plugin-security": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-2.1.1.tgz", - "integrity": "sha512-7cspIGj7WTfR3EhaILzAPcfCo5R9FbeWvbgsPYWivSurTBKW88VQxtP3c4aWMG9Hz/GfJlJVdXEJ3c8LqS+u2w==", + "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": { "safe-regex": "^2.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-plugin-sonarjs": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.25.1.tgz", - "integrity": "sha512-5IOKvj/GMBNqjxBdItfotfRHo7w48496GOu1hxdeXuD0mB1JBlDCViiLHETDTfA8pDAVSBimBEQoetRXYceQEw==", + "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, "engines": { "node": ">=16" }, "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + "eslint": "^8.0.0 || ^9.0.0" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "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": "^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==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "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==", + "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.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "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.9.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "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" @@ -2461,15 +2516,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": { @@ -2478,9 +2533,9 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" }, "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" @@ -2532,17 +2587,16 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "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.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -2552,9 +2606,9 @@ "dev": true }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "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", @@ -2568,11 +2622,11 @@ } }, "node_modules/form-data-encoder": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", - "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "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": ">= 14.17" + "node": ">= 18" } }, "node_modules/fromentries": { @@ -2650,19 +2704,11 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/gauge": { "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", @@ -2756,20 +2802,20 @@ } }, "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/get-tsconfig": { - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", - "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", + "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" @@ -2784,22 +2830,23 @@ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" }, "node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "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": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" + "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": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2842,39 +2889,37 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.6.0.tgz", + "integrity": "sha512-UzcJi88Hw//CurUIRa9Jxb0vgOCcuD/MNjwmXp633cyaRKkCWACkoqHCtfZv43b1kqXGg/fpOa8bwgacCeXsVg==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/got": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", - "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", + "version": "14.4.1", + "resolved": "https://registry.npmjs.org/got/-/got-14.4.1.tgz", + "integrity": "sha512-IvDJbJBUeexX74xNQuMIVgCRRuNOm5wuK+OC3Dc2pnSoh1AOmgc7JVj7WC+cJ4u0aPcO9KZ2frTXcqK4W/5qTQ==", "dependencies": { - "@sindresorhus/is": "^5.2.0", + "@sindresorhus/is": "^6.3.1", "@szmarczak/http-timer": "^5.0.1", "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", + "cacheable-request": "^12.0.1", "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", + "form-data-encoder": "^4.0.2", + "get-stream": "^8.0.1", + "http2-wrapper": "^2.2.1", "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" + "p-cancelable": "^4.0.1", + "responselike": "^3.0.0", + "type-fest": "^4.19.0" }, "engines": { - "node": ">=16" + "node": ">=20" }, "funding": { "url": "https://github.com/sindresorhus/got?sponsor=1" @@ -2886,12 +2931,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2932,18 +2971,6 @@ "node": ">=8" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2960,9 +2987,9 @@ "dev": true }, "node_modules/html-validate": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/html-validate/-/html-validate-8.18.1.tgz", - "integrity": "sha512-6NYRciFBQhVZH29fwDQxofPil0qm7MMSEDzDpZWu2U23Fnmv1WTuompP7fbzHYj6+CIJ4T/Q4hyWRCe0CCrsMg==", + "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": [ { @@ -2970,6 +2997,10 @@ "url": "https://github.com/sponsors/html-validate" } ], + "workspaces": [ + "docs", + "tests/vitest" + ], "dependencies": { "@babel/code-frame": "^7.10.0", "@html-validate/stylish": "^4.1.0", @@ -3011,15 +3042,15 @@ } }, "node_modules/html-validate/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dev": true, "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -3137,6 +3168,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", @@ -3177,33 +3209,6 @@ "node": ">=8" } }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - }, - "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", @@ -3333,27 +3338,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.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": ">=10" } }, "node_modules/istanbul-lib-processinfo": { @@ -3439,9 +3436,9 @@ } }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "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" @@ -3479,6 +3476,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", @@ -3700,9 +3706,9 @@ } }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -3810,6 +3816,7 @@ "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", @@ -3875,9 +3882,9 @@ "dev": true }, "node_modules/nise": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.9.tgz", - "integrity": "sha512-qOnoujW4SV6e40dYxJOb3uvuoPHtmLzIk4TFo+j0jPJoC+5Z9xja5qH5JZobEPsa8+YYphMrOSwnrshEhG2qww==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.0.0.tgz", + "integrity": "sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", @@ -3888,9 +3895,9 @@ } }, "node_modules/node-abi": { - "version": "3.57.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.57.0.tgz", - "integrity": "sha512-Dp+A9JWxRaKuHP35H77I4kCKesDy5HUDEmScia2FyncMTOXASMyg251F5PhFoDA5uqBrDDffiLpbqnrZmNXW+g==", + "version": "3.65.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz", + "integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==", "dependencies": { "semver": "^7.3.5" }, @@ -3899,12 +3906,12 @@ } }, "node_modules/node-addon-api": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.0.tgz", - "integrity": "sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==", + "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": "^16 || ^18 || >= 20" + "node": "^18 || ^20 || >= 21" } }, "node_modules/node-fetch": { @@ -3928,9 +3935,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", - "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "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", @@ -4159,6 +4166,7 @@ "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": "~1.1.2", @@ -4177,9 +4185,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", @@ -4194,7 +4202,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", @@ -4214,7 +4222,7 @@ "nyc": "bin/nyc.js" }, "engines": { - "node": ">=8.9" + "node": ">=18" } }, "node_modules/nyc/node_modules/cliui": { @@ -4264,6 +4272,7 @@ "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", @@ -4421,17 +4430,17 @@ } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -4447,11 +4456,11 @@ } }, "node_modules/p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-4.0.1.tgz", + "integrity": "sha512-wBowNApzd45EIKdO1LaU+LrMBwAcjfPaYtVzV3lmfM3gf8Z4CHZsiIqlM8TZZ8okYvh5A1cP6gTfCRQtwUpaUg==", "engines": { - "node": ">=12.20" + "node": ">=14.16" } }, "node_modules/p-limit": { @@ -4520,6 +4529,12 @@ "node": ">=8" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.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", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4570,41 +4585,35 @@ "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-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "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.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "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": { @@ -4653,11 +4662,11 @@ } }, "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==", "engines": { - "node": ">=12.0.0" + "node": ">=14.0.0" } }, "node_modules/pg-pool": { @@ -4669,13 +4678,13 @@ } }, "node_modules/pg-promise": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.6.0.tgz", - "integrity": "sha512-NDRPMfkv3ia89suWlJ4iGvP6X5YFrLJ2+9AIVISeBFFZ29Eb4FNXX9JaVb1p1OrpQkE2yT7igmXPL7UYQhk+6A==", + "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==", "dependencies": { "assert-options": "0.8.1", "pg": "8.11.5", - "pg-minify": "1.6.3", + "pg-minify": "1.6.4", "spex": "3.3.0" }, "engines": { @@ -4711,9 +4720,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": { @@ -5112,18 +5121,6 @@ "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/release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -5165,23 +5162,6 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.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", @@ -5233,6 +5213,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" @@ -5248,6 +5229,7 @@ "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", @@ -5302,12 +5284,9 @@ } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "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==", "bin": { "semver": "bin/semver.js" }, @@ -5315,22 +5294,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==", - "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==" - }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", @@ -5423,17 +5386,17 @@ } }, "node_modules/sinon": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-17.0.1.tgz", - "integrity": "sha512-wmwE19Lie0MLT+ZYNpDymasPHUKTaZHUH/pKEubRXIzySv9Atnlw+BUMGCzWgV7b7wO+Hw6f1TEOr0IUnmU8/g==", + "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/commons": "^3.0.1", "@sinonjs/fake-timers": "^11.2.2", "@sinonjs/samsam": "^8.0.0", - "diff": "^5.1.0", - "nise": "^5.1.5", - "supports-color": "^7.2.0" + "diff": "^5.2.0", + "nise": "^6.0.0", + "supports-color": "^7" }, "funding": { "type": "opencollective", @@ -5511,6 +5474,28 @@ "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", @@ -5666,16 +5651,13 @@ "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": { @@ -5799,6 +5781,7 @@ "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", @@ -5881,12 +5864,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" @@ -5908,9 +5890,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "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": [ { @@ -5927,8 +5909,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -5961,9 +5943,9 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -6038,6 +6020,15 @@ "node": ">=8" } }, + "node_modules/word-wrap": { + "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" + } + }, "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", diff --git a/package.json b/package.json index b0f36f3..61b6838 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@squeep/indie-auther", - "version": "1.1.0", + "version": "1.2.0", "description": "A stand-alone IndieAuth identity-provider service, for most of your IndieAuth endpoint needs.", "keywords": [ "IdP", @@ -12,18 +12,21 @@ ], "main": "server.js", "scripts": { + "audit": "npm audit", "coverage": "nyc npm test", "coverage-check": "nyc check-coverage", "eslint": "eslint server.js src", + "eslint:test": "eslint test", "test": "mocha --recursive" }, "pre-commit": [ "eslint", "coverage", - "coverage-check" + "coverage-check", + "audit" ], "engines": { - "node": "^14 >=14.18 || >=15.7" + "node": ">=20" }, "repository": { "type": "git", @@ -32,33 +35,29 @@ "author": "Justin Wind ", "license": "ISC", "dependencies": { - "@squeep/amqp-helper": "git+https://git.squeep.com/squeep-amqp-helper#v1.0.0", - "@squeep/api-dingus": "^2.1.0", - "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.4.0", - "@squeep/chores": "git+https://git.squeep.com/squeep-chores/#v1.0.1", - "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.6.0", - "@squeep/indieauth-helper": "^1.4.1", - "@squeep/logger-json-console": "^3.0.2", - "@squeep/mystery-box": "^2.0.2", - "@squeep/resource-authentication-module": "git+https://git.squeep.com/squeep-resource-authentication-module#v1.0.1", - "@squeep/roman": "^1.0.1", - "@squeep/web-linking": "^1.0.8", - "better-sqlite3": "^9.4.5", - "pg-promise": "^11.6.0", - "uuid": "^9.0.1" + "@squeep/amqp-helper": "git+https://git.squeep.com/squeep-amqp-helper#v1.0.1", + "@squeep/api-dingus": "^2", + "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.5.0", + "@squeep/chores": "git+https://git.squeep.com/squeep-chores/#v1.0.2", + "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.6.1", + "@squeep/indieauth-helper": "^1.4", + "@squeep/logger-json-console": "^3", + "@squeep/mystery-box": "^2", + "@squeep/roman": "^1", + "@squeep/web-linking": "^1", + "better-sqlite3": "^11", + "pg-promise": "^11", + "uuid": "^10" }, "devDependencies": { - "@squeep/test-helper": "git+https://git.squeep.com/squeep-test-helper#v1.0.1", - "eslint": "^8.57.0", - "eslint-plugin-n": "^16.6.2", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-security": "^2.1.1", - "eslint-plugin-sonarjs": "^0.25.1", - "html-validate": "^8.18.1", - "mocha": "^10.4.0", - "mocha-steps": "^1.3.0", - "nyc": "^15.1.0", - "pre-commit": "^1.2.2", - "sinon": "^17.0.1" + "@squeep/eslint-config": "^1", + "@squeep/test-helper": "git+https://git.squeep.com/squeep-test-helper#v2.0.0", + "eslint": "^9", + "html-validate": "^8", + "mocha": "^10", + "mocha-steps": "^1", + "nyc": "^17", + "pre-commit": "^1", + "sinon": "^18" } } diff --git a/src/chores.js b/src/chores.js index 4002158..bd21f6f 100644 --- a/src/chores.js +++ b/src/chores.js @@ -23,7 +23,7 @@ class Chores extends BaseChores { /** * Attempt to remove tokens which are expired or otherwise no longer valid. - * @param {Number} atLeastMsSinceLast + * @param {number} atLeastMsSinceLast minimum clean period */ async cleanTokens(atLeastMsSinceLast = this.options?.chores?.tokenCleanupMs || 0) { const _scope = _fileScope('cleanTokens'); @@ -47,7 +47,7 @@ class Chores extends BaseChores { /** * Attempt to remove ephemeral scopes which are no longer referenced by tokens. - * @param {Number} atLeastMsSinceLast + * @param {number} atLeastMsSinceLast minimum clean period */ async cleanScopes(atLeastMsSinceLast = this.options?.chores?.scopeCleanupMs || 0) { const _scope = _fileScope('cleanScopes'); diff --git a/src/common.js b/src/common.js index a9427c2..0855720 100644 --- a/src/common.js +++ b/src/common.js @@ -8,9 +8,9 @@ const randomBytesAsync = promisify(randomBytes); /** * Limit length of string to keep logs sane - * @param {String} str - * @param {Number} len - * @returns {String} + * @param {string} str str + * @param {number} len len + * @returns {string} str */ const logTruncate = (str, len) => { if (typeof str !== 'string' || str.toString().length <= len) { @@ -21,9 +21,9 @@ const logTruncate = (str, len) => { /** * Turn a snake into a camel. - * @param {String} snakeCase - * @param {String|RegExp} delimiter - * @returns {String} + * @param {string} snakeCase snake case + * @param {string | RegExp} delimiter delimiter + * @returns {string} camel case */ const camelfy = (snakeCase, delimiter = '_') => { if (!snakeCase || typeof snakeCase.split !== 'function') { @@ -38,7 +38,8 @@ const camelfy = (snakeCase, delimiter = '_') => { /** * Return an array containing x if x is not an array. - * @param {*} x + * @param {*} x x + * @returns {any[]} x[] */ const ensureArray = (x) => { if (x === undefined) { @@ -52,8 +53,8 @@ const ensureArray = (x) => { /** * Recursively freeze an object. - * @param {Object} o - * @returns {Object} + * @param {object} o obj + * @returns {object} frozen obj */ const freezeDeep = (o) => { Object.freeze(o); @@ -68,9 +69,13 @@ const freezeDeep = (o) => { }; -/** Oauth2.1 §3.2.3.1 +/** + * Oauth2.1 §3.2.3.1 * %x20-21 / %x23-5B / %x5D-7E - * @param {String} char + * ' '-'!' / '#'-'[' / ']'-'~' + * not allowed: control characters, '"', '\' + * @param {string} char character + * @returns {boolean} is valid */ const validErrorChar = (char) => { const value = char.charCodeAt(0); @@ -82,8 +87,8 @@ const validErrorChar = (char) => { /** * Determine if an OAuth error message is valid. - * @param {String} error - * @returns {Boolean} + * @param {string} error error + * @returns {boolean} is valid */ const validError = (error) => { return error && error.split('').filter((c) => !validErrorChar(c)).length === 0 || false; @@ -93,7 +98,8 @@ const validError = (error) => { /** * OAuth2.1 §3.2.2.1 * scope-token = 1*( %x21 / %x23-5B / %x5D-7E ) - * @param {String} char + * @param {string} char char + * @returns {boolean} is valid */ const validScopeChar = (char) => { const value = char.charCodeAt(0); @@ -105,8 +111,8 @@ const validScopeChar = (char) => { /** * Determine if a scope has a valid name. - * @param {String} scope - * @returns {Boolean} + * @param {string} scope scope + * @returns {boolean} is valid */ const validScope = (scope) => { return scope && scope.split('').filter((c) => !validScopeChar(c)).length === 0 || false; @@ -115,7 +121,8 @@ const validScope = (scope) => { /** * - * @param {Number} bytes + * @param {number} bytes bytes + * @returns {string} base64 random string */ const newSecret = async (bytes = 64) => { return (await randomBytesAsync(bytes * 3 / 4)).toString('base64'); @@ -124,8 +131,8 @@ const newSecret = async (bytes = 64) => { /** * Convert a Date object to epoch seconds. - * @param {Date=} date - * @returns {Number} + * @param {Date=} date date + * @returns {number} epoch */ const dateToEpoch = (date) => { const dateMs = date ? date.getTime() : Date.now(); @@ -138,10 +145,16 @@ const omit = (o, props) => { }; +/** + * @typedef {object} ConsoleLike + * @property {Function} debug log debug + */ + /** * Log Mystery Box statistics events. - * @param {Console} logger - * @param {String} scope + * @param {ConsoleLike} logger logger instance + * @param {string} scope scope + * @returns {Function} stat logger */ const mysteryBoxLogger = (logger, scope) => { return (s) => { diff --git a/src/db/abstract.js b/src/db/abstract.js index 953034d..a127c39 100644 --- a/src/db/abstract.js +++ b/src/db/abstract.js @@ -21,7 +21,7 @@ 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. - */ + */ async initialize() { const _scope = _fileScope('initialize'); @@ -39,15 +39,15 @@ class Database { /** - * @typedef {Object} SchemaVersionObject - * @property {Number} major - * @property {Number} minor - * @property {Number} patch + * @typedef {object} SchemaVersionObject + * @property {number} major major + * @property {number} minor minor + * @property {number} patch patch */ /** * Query the current schema version. * This is a standalone query function, as it is called before statements are loaded. - * @returns {Promise} + * @returns {Promise} schema version */ async _currentSchema() { this._notImplemented('_currentSchema', arguments); @@ -73,7 +73,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) { @@ -101,9 +101,9 @@ class Database { * - infinites * - null * - uuid - * @param {Object} object - * @param {String[]} properties - * @param {String[]} types + * @param {object} object object + * @param {string[]} properties properties + * @param {string[]} types types */ _ensureTypes(object, properties, types) { const _scope = _fileScope('_ensureTypes'); @@ -157,14 +157,14 @@ class Database { /** - * @typedef {Object} Authentication - * @property {String} identifier - * @property {String=} credential - * @property {Date} created - * @property {Date=} lastAuthentication + * @typedef {object} Authentication + * @property {string} identifier identifier + * @property {string=} credential credential + * @property {Date} created created + * @property {Date=} lastAuthentication last authentication */ /** - * @param {Authentication} authentication + * @param {Authentication} authentication authentication */ _validateAuthentication(authentication) { [ @@ -177,14 +177,14 @@ class Database { /** - * @typedef {Object} Resource - * @property {String} resourceId - uuid - * @property {String} secret - * @property {String} description - * @property {Date} created + * @typedef {object} Resource + * @property {string} resourceId uuid + * @property {string} secret secret + * @property {string} description description + * @property {Date} created created at */ /** - * @param {Resource} resource + * @param {Resource} resource resource */ _validateResource(resource) { [ @@ -196,24 +196,24 @@ class Database { /** - * @typedef {Object} Token - * @property {String} codeId - uuid - * @property {String} profile - * @property {Date} created - * @property {Date=} expires - * @property {Date=} refreshExpires - * @property {Date=} refreshed - * @property {*=} duration - * @property {*=} refreshDuration - * @property {Number|BigInt=} refresh_count - * @property {Boolean} is_revoked - * @property {Boolean} is_token - * @property {String} client_id - * @property {String[]} scopes - * @property {Object=} profileData + * @typedef {object} Token + * @property {string} codeId uuid + * @property {string} profile profile + * @property {Date} created created at + * @property {Date=} expires expires at + * @property {Date=} refreshExpires refresh expires at + * @property {Date=} refreshed refreshed at + * @property {*=} duration duration + * @property {*=} refreshDuration refresh duration + * @property {number | bigint=} refresh_count refresh count + * @property {boolean} is_revoked is revoked + * @property {boolean} is_token is token + * @property {string} client_id client id + * @property {string[]} scopes scopes + * @property {object=} profileData profile data */ /** - * @param {Token} token + * @param {Token} token token */ _validateToken(token) { [ @@ -233,8 +233,8 @@ class Database { * Interface methods need implementations. Ensure the db-interaction * methods on the base class call this, so they may be overridden by * implementation classes. - * @param {String} method - * @param {arguments} args + * @param {string} method method + * @param {arguments} args args */ _notImplemented(method, args) { this.logger.error(_fileScope(method), 'abstract method called', Array.from(args)); @@ -244,7 +244,7 @@ class Database { /** * Get all the almanac entries. - * @param {*} dbCtx + * @param {*} dbCtx db context */ async almanacGetAll(dbCtx) { this._notImplemented('almanacGetAll', arguments); @@ -253,9 +253,9 @@ class Database { /** * Insert or update an almanac entry. - * @param {*} dbCtx - * @param {String} event - * @param {Date=} date + * @param {*} dbCtx db context + * @param {string} event event + * @param {Date=} date date */ async almanacUpsert(dbCtx, event, date) { this._notImplemented('almanacUpsert', arguments); @@ -264,9 +264,9 @@ class Database { /** * Fetch the authentication record for an identifier. - * @param {*} dbCtx - * @param {String} identifier - * @returns {Promise} + * @param {*} dbCtx db context + * @param {string} identifier identifier + * @returns {Promise} authentication */ async authenticationGet(dbCtx, identifier) { this._notImplemented('authenticationGet', arguments); @@ -276,8 +276,8 @@ class Database { /** * Update the authentication record for the identifier that * correct credentials have been supplied. - * @param {*} dbCtx - * @param {String} identifier + * @param {*} dbCtx db context + * @param {string} identifier identifier * @returns {Promise} */ async authenticationSuccess(dbCtx, identifier) { @@ -287,10 +287,10 @@ class Database { /** * Insert or update the credential for an identifier. - * @param {*} dbCtx - * @param {String} identifier - * @param {String} credential - * @param {String=} otpKey + * @param {*} dbCtx db context + * @param {string} identifier identifier + * @param {string} credential credential + * @param {string=} otpKey otp key * @returns {Promise} */ async authenticationUpsert(dbCtx, identifier, credential, otpKey) { @@ -300,9 +300,9 @@ class Database { /** * Update the otpKey for an identifier. - * @param {*} dbCtx - * @param {String} identifier - * @param {String=} otpKey + * @param {*} dbCtx db context + * @param {string} identifier identifier + * @param {string=} otpKey otp key * @returns {Promise} */ async authenticationUpdateOTPKey(dbCtx, identifier, otpKey) { @@ -312,9 +312,9 @@ class Database { /** * Update the credential for an identifier. - * @param {*} dbCtx - * @param {String} identifier - * @param {String} credential + * @param {*} dbCtx db context + * @param {string} identifier identifier + * @param {string} credential credential * @returns {Promise} */ async authenticationUpdateCredential(dbCtx, identifier, credential) { @@ -324,9 +324,9 @@ class Database { /** * Determine if profile url is known to this service. - * @param {*} dbCtx - * @param {String} profile - * @returns {Promise} + * @param {*} dbCtx db context + * @param {string} profile profile + * @returns {Promise} is valid */ async profileIsValid(dbCtx, profile) { this._notImplemented('profileGet', arguments); @@ -336,9 +336,9 @@ class Database { /** * Insert a new relationship between a profile endpoint and * an authenticated identifier. - * @param {*} dbCtx - * @param {String} profile - * @param {String} identifier + * @param {*} dbCtx db context + * @param {string} profile profile + * @param {string} identifier identifier * @returns {Promise} */ async profileIdentifierInsert(dbCtx, profile, identifier) { @@ -348,9 +348,9 @@ class Database { /** * Adds a scope to be available for a profile to include on any authorization request. - * @param {*} dbCtx - * @param {String} profile - * @param {String} scope + * @param {*} dbCtx db context + * @param {string} profile profile + * @param {string} scope scope * @returns {Promise} */ async profileScopeInsert(dbCtx, profile, scope) { @@ -359,24 +359,26 @@ class Database { /** - * @typedef {Object} ScopeDetails - * @property {String} description - * @property {String[]=} profiles + * @typedef {object} ScopeDetails + * @property {string} description description + * @property {string[]=} profiles profiles + */ + /** + * @typedef {object} Profile + * @property {ScopeDetails} scope scope */ /** - * @typedef {Object.} ProfileScopes - * @property {Object.} profile - * @property {Object.} profile.scope + * @typedef {{[profile: string]: Profile}} ProfileScopes */ /** - * @typedef {Object.} ScopeIndex - * @property {ScopeDetails} scope + * @typedef {{[scope: string]: ScopeDetails}} ScopeIndex + * @property {ScopeDetails} scope scope details */ /** - * @typedef {Object} ProfilesScopesReturn - * @property {ProfileScopes} profileScopes - * @property {ScopeIndex} scopeIndex - * @property {String[]} profiles + * @typedef {object} ProfilesScopesReturn + * @property {ProfileScopes} profileScopes profile scopes + * @property {ScopeIndex} scopeIndex scope index + * @property {string[]} profiles profiles */ /** * Returns an object containing: @@ -384,9 +386,9 @@ class Database { * which each contain a description of the scope and a list of profiles offering it * - an object with scopes as keys to the same scope objects * - a list of profiles - * @param {*} dbCtx - * @param {String} identifier - * @returns {Promise} + * @param {*} dbCtx db context + * @param {string} identifier identifier + * @returns {Promise} profiles scopes */ async profilesScopesByIdentifier(dbCtx, identifier) { this._notImplemented('profilesScopesByIdentifier', arguments); @@ -395,18 +397,18 @@ class Database { /** * @typedef ProfileScopesRow - * @property profile - * @property scope - * @property description - * @property application - * @property isPermanent - * @property isManuallyAdded + * @property {string} profile profile + * @property {string} scope scope + * @property {string} description description + * @property {string} application application + * @property {boolean} isPermanent avoid cleanup + * @property {boolean} isManuallyAdded avoid cleanup */ /** * Convert db row data into associative structures. * Same behavior is shared by multiple engines. - * @param {ProfileScopesRow[]} profileScopesRows - * @returns {ProfileScopesReturn} + * @param {ProfileScopesRow[]} profileScopesRows profile scopes row + * @returns {ProfilesScopesReturn} profiles scopes */ static _profilesScopesBuilder(profileScopesRows) { const scopeIndex = {}; @@ -445,9 +447,9 @@ class Database { /** * Sets list of additional scopes available to profile. - * @param {*} dbCtx - * @param {String} profile - * @param {String[]} scopes + * @param {*} dbCtx db context + * @param {string} profile profile + * @param {string[]} scopes scopes * @returns {Promise} */ async profileScopesSetAll(dbCtx, profile, scopes) { @@ -457,20 +459,19 @@ class Database { /** * Create (or revoke a duplicate) code as a token entry. - * @param {*} dbCtx - * @param {Object} data - * @param {String} data.codeId - * @param {Date} data.created - * @param {Boolean} data.isToken - * @param {String} data.clientId - * @param {String} data.profile - profile uri - * @param {String} data.identifier - * @param {String[]} data.scopes - * @param {Number|Null} data.lifespanSeconds - null sets expiration to Infinity - * @param {Number|Null} data.refreshLifespanSeconds - null sets refresh to none - * @param {String|Null} data.resource - * @param {Object|Null} data.profileData - profile data from profile uri - * @returns {Promise} whether redemption was successful + * @param {*} dbCtx db context + * @param {object} data data + * @param {string} data.codeId code id + * @param {Date} data.created created at + * @param {boolean} data.isToken is token + * @param {string} data.clientId client id + * @param {string} data.profile profile uri + * @param {string} data.identifier identifier + * @param {string[]} data.scopes scopesx + * @param {number | null} data.lifespanSeconds null sets expiration to Infinity + * @param {number | null} data.refreshLifespanSeconds null sets refresh to none + * @param {object | null} data.profileData profile data from profile uri + * @returns {Promise} whether redemption was successful */ async redeemCode(dbCtx, { codeId, created, isToken, clientId, profile, identifier, scopes, lifespanSeconds, refreshLifespanSeconds, profileData } = {}) { this._notImplemented('redeemCode', arguments); @@ -478,18 +479,18 @@ class Database { /** - * @typedef {Object} RefreshedToken - * @property {Date} expires - * @property {Date} refreshExpires - * @property {String[]=} scopes if scopes were reduced + * @typedef {object} RefreshedToken + * @property {Date} expires expires at + * @property {Date} refreshExpires refresh expires at + * @property {string[]=} scopes if scopes were reduced */ /** * Redeem a refresh token to renew token codeId. - * @param {*} dbCtx - * @param {String} codeId - * @param {Date} refreshed - * @param {String[]} removeScopes - * @returns {Promise} + * @param {*} dbCtx db context + * @param {string} codeId code id + * @param {Date} refreshed refreshed at + * @param {string[]} removeScopes remove scopes + * @returns {Promise} refreshed token */ async refreshCode(dbCtx, codeId, refreshed, removeScopes) { this._notImplemented('refreshCode', arguments); @@ -498,9 +499,9 @@ class Database { /** * Fetch a resource server record. - * @param {*} dbCtx - * @param {String} identifier uuid - * @returns {Promise} + * @param {*} dbCtx db context + * @param {string} resourceId uuid + * @returns {Promise} resource */ async resourceGet(dbCtx, resourceId) { this._notImplemented('resourceGet', arguments); @@ -509,10 +510,10 @@ class Database { /** * Create, or update description of, a resourceId. - * @param {*} dbCtx - * @param {String=} resourceId uuid - * @param {String=} secret - * @param {String=} description + * @param {*} dbCtx db context + * @param {string=} resourceId uuid + * @param {string=} secret secret + * @param {string=} description description * @returns {Promise} */ async resourceUpsert(dbCtx, resourceId, secret, description) { @@ -522,10 +523,11 @@ class Database { /** * Register a scope and its description. - * @param {*} dbCtx - * @param {String} scope - * @param {String} application - * @param {String} description + * @param {*} dbCtx db context + * @param {string} scope scope + * @param {string} application application + * @param {string} description description + * @param {boolean} manuallyAdded is manually added * @returns {Promise} */ async scopeUpsert(dbCtx, scope, application, description, manuallyAdded = false) { @@ -535,9 +537,9 @@ class Database { /** * Remove a non-permanent scope if it is not currently in use. - * @param {*} dbCtx - * @param {String} scope - * @returns {Promise} + * @param {*} dbCtx db context + * @param {string} scope scope + * @returns {Promise} deleted */ async scopeDelete(dbCtx, scope) { this._notImplemented('scopeDelete', arguments); @@ -545,16 +547,16 @@ class Database { /** - * @typedef {Number|BigInt} CleanupResult + * @typedef {number | bigint} CleanupResult */ /** - * @typedef {Object} CleanupResult + * @alias {object} CleanupResult */ /** * Remove any non-permanent and non-manually-created scopes not currently in use. - * @param {*} dbCtx - * @param {Number} atLeastMsSinceLast skip cleanup if already executed this recently - * @returns {Promise} + * @param {*} dbCtx db context + * @param {number} atLeastMsSinceLast skip cleanup if already executed this recently + * @returns {Promise} cleanup result */ async scopeCleanup(dbCtx, atLeastMsSinceLast) { this._notImplemented('scopeClean', arguments); @@ -563,10 +565,10 @@ class Database { /** * Forget tokens after they have expired, and redeemed codes after they have expired. - * @param {*} dbCtx - * @param {Number} codeLifespanSeconds - * @param {Number} atLeastMsSinceLast skip cleanup if already executed this recently - * @returns {Promise} + * @param {*} dbCtx db context + * @param {number} codeLifespanSeconds code lifespan seconds + * @param {number} atLeastMsSinceLast skip cleanup if already executed this recently + * @returns {Promise} cleanup result */ async tokenCleanup(dbCtx, codeLifespanSeconds, atLeastMsSinceLast) { this._notImplemented('tokenCleanup', arguments); @@ -575,9 +577,9 @@ class Database { /** * Look up a redeemed token by code_id. - * @param {*} dbCtx - * @param {String} codeId - * @returns {Promise} + * @param {*} dbCtx db context + * @param {string} codeId code id + * @returns {Promise} token */ async tokenGetByCodeId(dbCtx, codeId) { this._notImplemented('tokenGetByCodeId', arguments); @@ -586,8 +588,8 @@ class Database { /** * Sets a redeemed token as revoked. - * @param {*} dbCtx - * @param {String} codeId - uuid + * @param {*} dbCtx db context + * @param {string} codeId - uuid * @returns {Promise} */ async tokenRevokeByCodeId(dbCtx, codeId) { @@ -597,8 +599,8 @@ class Database { /** * Revoke the refreshability of a codeId. - * @param {*} dbCtx - * @param {String} codeId - uuid + * @param {*} dbCtx db context + * @param {string} codeId - uuid * @returns {Promise} */ async tokenRefreshRevokeByCodeId(dbCtx, codeId) { @@ -608,26 +610,27 @@ class Database { /** * Get all tokens assigned to identifier. - * @param {*} dbCtx - * @param {String} identifier - * @returns {Promise} + * @param {*} dbCtx db context + * @param {string} identifier identifier + * @returns {Promise} token */ async tokensGetByIdentifier(dbCtx, identifier) { this._notImplemented('tokensGetByIdentifier', arguments); } - /** @typedef {Object} RedeemedTicketData - * @property {String} subject - * @property {String} resource - * @property {String=} iss - * @property {String} ticket - * @property {String} token + /** + * @typedef {object} RedeemedTicketData + * @property {string} subject subject + * @property {string} resource resource + * @property {string=} iss issuer + * @property {string} ticket ticket + * @property {string} token token */ /** * Persist details of a redeemed ticket. - * @param {*} dbCtx - * @param {RedeemedTicketData} redeemedData + * @param {*} dbCtx db context + * @param {RedeemedTicketData} redeemedData redeemed data * @returns {Promise} */ async ticketRedeemed(dbCtx, redeemedData) { @@ -637,18 +640,20 @@ class Database { /** * Update details of a redeemed ticket that it has been published. - * @param {*} dbCtx - * @param {RedeemedTicketData} redeemedData + * @param {*} dbCtx db context + * @param {RedeemedTicketData} redeemedData redeemed data * @returns {Promise} */ async ticketTokenPublished(dbCtx, redeemedData) { this._notImplemented('ticketTokenPublished', arguments); } + /** * Retrieve redeemed tokens which have not yet been published to queue. - * @param {Number} limit - * @returns {Promise} + * @param {*} dbCtx db context + * @param {number} limit limit + * @returns {Promise} redeemed but not published */ async ticketTokenGetUnpublished(dbCtx, limit) { this._notImplemented('ticketTokenGetUnpublished', arguments); diff --git a/src/db/schema-version-helper.js b/src/db/schema-version-helper.js index 65a1e39..4582a87 100644 --- a/src/db/schema-version-helper.js +++ b/src/db/schema-version-helper.js @@ -10,17 +10,17 @@ const path = require('path'); */ /** - * @typedef {Object} SchemaVersionObject - * @property {Number} major - * @property {Number} minor - * @property {Number} patch + * @typedef {object} SchemaVersionObject + * @property {number} major major + * @property {number} minor minor + * @property {number} patch patch */ /** * Split a dotted version string into parts. - * @param {String} v - * @returns {SchemaVersionObject} + * @param {string} v version string + * @returns {SchemaVersionObject} version object */ function schemaVersionStringToObject(v) { const [ major, minor, patch ] = v.split('.', 3).map((x) => parseInt(x, 10)); @@ -30,8 +30,9 @@ function schemaVersionStringToObject(v) { /** * Render a version object numerically. - * @param {SchemaVersionObject} v - * @returns {Number} + * Assumes no part will be greater than 1000. + * @param {SchemaVersionObject} v version object + * @returns {number} number */ function schemaVersionObjectToNumber(v) { const vScale = 1000; @@ -41,8 +42,8 @@ function schemaVersionObjectToNumber(v) { /** * Convert dotted version string into number. - * @param {String} v - * @returns {Number} + * @param {string} v version string + * @returns {number} number */ function schemaVersionStringToNumber(v) { return schemaVersionObjectToNumber(schemaVersionStringToObject(v)); @@ -51,9 +52,9 @@ function schemaVersionStringToNumber(v) { /** * Version string comparison, for sorting. - * @param {String} a - * @param {String} b - * @returns {Number} + * @param {string} a version string + * @param {string} b version string + * @returns {number} cmp */ function schemaVersionStringCmp(a, b) { return schemaVersionStringToNumber(a) - schemaVersionStringToNumber(b); @@ -62,9 +63,10 @@ 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 schema dir + * @param {string} name name + * @param {string} migrationFile migration file + * @returns {boolean} is */ function isSchemaMigrationDirectory(schemaDir, name, migrationFile = 'apply.sql') { // eslint-disable-next-line security/detect-non-literal-fs-filename @@ -75,7 +77,7 @@ function isSchemaMigrationDirectory(schemaDir, name, migrationFile = 'apply.sql' // eslint-disable-next-line security/detect-non-literal-fs-filename applyStat = fs.statSync(path.join(schemaDir, name, migrationFile)); return applyStat.isFile(); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars return false; } } @@ -86,8 +88,8 @@ function isSchemaMigrationDirectory(schemaDir, name, migrationFile = 'apply.sql' /** * Return an array of schema migration directory names within engineDir, * sorted in increasing order. - * @param {String} engineDir - * @returns {String[]} + * @param {string} engineDir path to implementation + * @returns {string[]} versions */ function allSchemaVersions(engineDir) { const schemaDir = path.join(engineDir, 'sql', 'schema'); @@ -101,12 +103,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 implementation + * @param {SchemaVersionObject} current version + * @param {object} supported range of supported versions + * @param {SchemaVersionObject} supported.min minimum version + * @param {SchemaVersionObject} supported.max maximum version + * @returns {string[]} applicable versions */ function unappliedSchemaVersions(engineDir, current, supported) { const min = schemaVersionObjectToNumber(supported.min); @@ -128,4 +130,4 @@ module.exports = { isSchemaMigrationDirectory, allSchemaVersions, unappliedSchemaVersions, -}; \ No newline at end of file +}; diff --git a/src/db/sqlite/index.js b/src/db/sqlite/index.js index a618b9a..2dd75b2 100644 --- a/src/db/sqlite/index.js +++ b/src/db/sqlite/index.js @@ -60,8 +60,8 @@ class DatabaseSQLite extends Database { /** * Boolean to 0/1 representation for SQLite params. - * @param {Boolean} bool - * @returns {Number} + * @param {boolean} bool boolean + * @returns {number} number */ static _booleanToNumeric(bool) { // eslint-disable-next-line security/detect-object-injection @@ -84,7 +84,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(); @@ -139,7 +139,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); diff --git a/src/logger/data-sanitizers.js b/src/logger/data-sanitizers.js index 5494d27..df653d6 100644 --- a/src/logger/data-sanitizers.js +++ b/src/logger/data-sanitizers.js @@ -2,9 +2,9 @@ /** * Scrub credential from POST login body data. - * @param {Object} data - * @param {Boolean} sanitize - * @returns {Boolean} + * @param {object} data data + * @param {boolean} sanitize do sanitize + * @returns {boolean} did/would sanitize */ function sanitizePostCredential(data, sanitize = true) { let unclean = false; @@ -29,9 +29,9 @@ function sanitizePostCredential(data, sanitize = true) { /** * Scrub sensitive data from context. - * @param {Object} data - * @param {Boolean} sanitize - * @returns {Boolean} + * @param {object} data data + * @param {boolean} sanitize do sanitize + * @returns {boolean} did/would sanitize */ function sanitizeContext(data, sanitize = true) { let unclean = false; @@ -78,8 +78,9 @@ function sanitizeContext(data, sanitize = true) { * Reduce logged data about scopes from profilesScopes. * For all referenced scopes, only include profiles list. * Remove scopes without profile references from scopeIndex. - * @param {Object} data - * @param {Boolean} sanitize + * @param {object} data data + * @param {boolean} sanitize do sanitize + * @returns {boolean} did/would sanitize */ function reduceScopeVerbosity(data, sanitize = true) { let unclean = false; @@ -114,8 +115,8 @@ function reduceScopeVerbosity(data, sanitize = true) { /** * Return any scope entries on an object, and whether sanitization is needed. - * @param {Object=} obj - * @returns {Object} + * @param {object=} obj obj + * @returns {object} obj */ const _scopesFrom = (obj) => { const scopesEntries = Object.entries(obj?.scopeIndex || {}); @@ -130,21 +131,21 @@ const _scopesFrom = (obj) => { /** - * @typedef {[String, Object]} ScopeEntry + * @typedef {[string, object]} ScopeEntry */ /** * Return new list of entries with scrubbed scopeDetails. - * @param {ScopeEntry[]} entries - * @returns {ScopeEntry[]} + * @param {ScopeEntry[]} entries entries + * @returns {ScopeEntry[]} entries */ const _scopeEntriesScrubber = (entries) => entries.map(([scopeName, scopeDetails]) => ([scopeName, { profiles: scopeDetails.profiles }])); /** * Create a new profilesScopes type object with scrubbed scope details. - * @param {ScopeEntry[]} scopesEntries - * @param {ScopeEntry[]} profilesEntries - * @returns {Object} + * @param {ScopeEntry[]} scopesEntries entries + * @param {ScopeEntry[]} profilesEntries entries + * @returns {object} profilesScopes */ const _sanitizeProfilesScopes = (scopesEntries, profilesEntries) => { const referencedScopesEntries = scopesEntries.filter(([_scopeName, scopeDetails]) => scopeDetails?.profiles?.length); // eslint-disable-line no-unused-vars diff --git a/src/manager.js b/src/manager.js index 398b409..ce544b9 100644 --- a/src/manager.js +++ b/src/manager.js @@ -1,3 +1,4 @@ +/* eslint-disable sonarjs/no-duplicate-string */ 'use strict'; const common = require('./common'); @@ -18,6 +19,10 @@ const scopeSplitRE = / +/; const supportedCodeChallengeMethods = ['S256', 'SHA256']; +/** + * @typedef {import('node:http')} http + */ + class Manager { constructor(logger, db, options) { this.options = options; @@ -64,12 +69,12 @@ class Manager { /** * Add an error to a session, keeping only the most-severe code, but all descriptions. * This error is sent along on the redirection back to client endpoint. - * @param {Object} ctx - * @param {Object} ctx.session - * @param {String[]=} ctx.session.errorDescriptions - * @param {String=} ctx.session.error - * @param {String} error - * @param {String} errorDescription + * @param {object} ctx context + * @param {object} ctx.session session + * @param {string[]=} ctx.session.errorDescriptions errors + * @param {string=} ctx.session.error error + * @param {string} error error + * @param {string} errorDescription error */ static _setError(ctx, error, errorDescription) { const errorPrecedence = [ // By increasing severity @@ -109,7 +114,7 @@ class Manager { * The authorization server MUST include the HTTP Cache-Control response * header field with a value of no-store in any response * containing tokens, credentials, or other sensitive information. - * @param {http.ServerResponse} res + * @param {http.ServerResponse} res response */ static _sensitiveResponse(res) { Object.entries({ @@ -121,8 +126,8 @@ class Manager { /** * Sets params entries as url search parameters. - * @param {URL} url - * @param {Object} params + * @param {URL} url url + * @param {object} params parameters */ static _setSearchParams(url, params) { Object.entries(params).forEach((param) => url.searchParams.set(...param)); @@ -131,9 +136,8 @@ class Manager { /** * Serve the informational root page. - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getRoot(res, ctx) { const _scope = _fileScope('getRoot'); @@ -146,8 +150,8 @@ class Manager { /** * Serve the metadata for this service. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getMeta(res, ctx) { const _scope = _fileScope('getMeta'); @@ -187,8 +191,8 @@ class Manager { * Process an authorization request from a client. * User has authenticated, check if user matches profile, * present user with consent form. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getAuthorization(res, ctx) { const _scope = _fileScope('getAuthorization'); @@ -306,7 +310,7 @@ class Manager { /** * Validates, fetches, and parses client_id url, populating clientIdentifier with client h-app data. - * @param {Object} ctx + * @param {object} ctx context */ async _clientIdRequired(ctx) { if (ctx.queryParams['client_id']) { @@ -332,7 +336,7 @@ class Manager { /** * Ensure redirect_uri exists and is corroborated by clientIdentifier data. - * @param {Object} ctx + * @param {object} ctx context */ static _redirectURIRequired(ctx) { if (ctx.queryParams['redirect_uri']) { @@ -355,7 +359,7 @@ class Manager { } } } - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars Manager._setError(ctx, 'invalid_request', 'invalid value for parameter \'redirect_uri\''); } } else { @@ -366,7 +370,7 @@ class Manager { /** * response_type must be valid - * @param {Object} ctx + * @param {object} ctx context */ static _responseTypeRequired(ctx) { ctx.session.responseType = ctx.queryParams['response_type']; @@ -383,7 +387,7 @@ class Manager { /** * A state parameter must be present - * @param {Object} ctx + * @param {object} ctx context */ static _stateRequired(ctx) { ctx.session.state = ctx.queryParams['state']; @@ -397,7 +401,7 @@ class Manager { /** * A code_challenge_method must be present and valid - * @param {Object} ctx + * @param {object} ctx context */ _codeChallengeMethodRequired(ctx) { ctx.session.codeChallengeMethod = ctx.queryParams['code_challenge_method']; @@ -416,7 +420,7 @@ class Manager { /** * A code_challenge must be present - * @param {Object} ctx + * @param {object} ctx context */ _codeChallengeRequired(ctx) { ctx.session.codeChallenge = ctx.queryParams['code_challenge']; @@ -435,7 +439,7 @@ class Manager { /** * Scopes may be present, with one known combination limitation - * @param {Object} ctx + * @param {object} ctx context */ _scopeOptional(ctx) { const _scope = _fileScope('_scopeOptional'); @@ -460,14 +464,14 @@ class Manager { /** * Parses me, if provided - * @param {Object} ctx + * @param {object} ctx context */ async _meOptional(ctx) { const me = ctx.queryParams['me']; if (me) { try { ctx.session.me = await this.communication.validateProfile(me); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars ctx.session.me = undefined; } } @@ -476,8 +480,8 @@ class Manager { /** * Ensure authenticated identifier matches profile. - * @param {Object} ctx - * @returns {Boolean} + * @param {object} ctx context + * @returns {boolean} is valid */ _profileValidForIdentifier(ctx) { const _scope = _fileScope('_profileValidForIdentifier'); @@ -493,10 +497,10 @@ class Manager { /** * Get numeric value from form field data. - * @param {*} ctx - * @param {String} field - * @param {String} customField - * @returns {Number=} + * @param {*} ctx context + * @param {string} field field + * @param {string} customField custom field + * @returns {number=} lifespan */ _parseLifespan(ctx, field, customField) { const _scope = _fileScope('_parseLifespan'); @@ -528,8 +532,8 @@ class Manager { /** * Validate any accepted scopes, ensure uniqueness, return as array. - * @param {Object} ctx - * @returns {String=} + * @param {object} ctx context + * @returns {string[]} scopes */ _parseConsentScopes(ctx) { const _scope = _fileScope('_ingestConsentScopes'); @@ -561,8 +565,8 @@ class Manager { /** * Parse and validate selected me is a valid profile option. - * @param {Object} ctx - * @returns {URL} + * @param {object} ctx context + * @returns {URL} url */ _parseConsentMe(ctx) { const _scope = _fileScope('_parseConsentMe'); @@ -585,8 +589,8 @@ class Manager { /** * Get up-to-date profile data from selected profile endpoint. - * @param {Object} ctx - * @returns {Promise} + * @param {object} ctx context + * @returns {Promise} profile data */ async _fetchConsentProfileData(ctx) { const _scope = _fileScope('_fetchConsentProfileData'); @@ -624,8 +628,8 @@ class Manager { * expires-seconds - optional custom lifespan * refresh - optional refresh lifespan * refresh-seconds - optional custom refresh lifespan - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async postConsent(res, ctx) { const _scope = _fileScope('postConsent'); @@ -728,8 +732,8 @@ class Manager { /** * Redeem a code for a profile url, and maybe more profile info. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async postAuthorization(res, ctx) { const _scope = _fileScope('postAuthorization'); @@ -786,8 +790,8 @@ class Manager { /** * Ingest an incoming authorization redemption request, parsing fields * onto a new session object on the context. - * @param {*} dbCtx - * @param {Object} ctx + * @param {object} ctx context + * @returns {Promise} */ async _ingestPostAuthorizationRequest(ctx) { const _scope = _fileScope('_ingestPostAuthorizationRequest'); @@ -825,7 +829,7 @@ class Manager { /** * Unpack the session data from provided code overtop of context session .. - * @param {Object} ctx + * @param {object} ctx context */ async _restoreSessionFromCode(ctx) { const _scope = _fileScope('_restoreSessionFromCode'); @@ -873,7 +877,7 @@ class Manager { /** * Ensure provided client_id matches session clientId. - * @param {Object} ctx + * @param {object} ctx context */ _checkSessionMatchingClientId(ctx) { const _scope = _fileScope('_checkSessionMatchingClientId'); @@ -883,7 +887,7 @@ class Manager { try { clientId = new URL(clientId); ctx.session.clientId = new URL(ctx.session.clientId); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.debug(_scope, 'un-parsable client_id url', { ctx }); delete ctx.session.clientId; Manager._setError(ctx, 'invalid_request', 'malformed client_id'); @@ -901,7 +905,7 @@ class Manager { /** - * @param {Object} ctx + * @param {object} ctx context */ _checkSessionMatchingRedirectUri(ctx) { const _scope = _fileScope('_checkSessionMatchingClientId'); @@ -911,7 +915,7 @@ class Manager { try { redirectUri = new URL(redirectUri); ctx.session.redirectUri = new URL(ctx.session.redirectUri); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.debug(_scope, 'un-parsable redirect_uri url', { ctx }); delete ctx.session.redirectUri; Manager._setError(ctx, 'invalid_request', 'malformed redirect_url'); @@ -930,9 +934,9 @@ class Manager { /** * Validate grant_type, either persist on session or set error. - * @param {Object} ctx - * @param {String[]} validGrantTypes - * @param {Boolean} treatEmptyAs + * @param {object} ctx context + * @param {string[]} validGrantTypes grant types + * @param {string=} treatEmptyAs grant type */ _checkGrantType(ctx, validGrantTypes = ['authorization_code'], treatEmptyAs = 'authorization_code') { const _scope = _fileScope('_checkGrantType'); @@ -950,7 +954,7 @@ class Manager { /** - * @param {Object} ctx + * @param {object} ctx context */ _checkSessionMatchingCodeVerifier(ctx) { const _scope = _fileScope('_checkSessionMatchingCodeVerifier'); @@ -981,9 +985,9 @@ class Manager { /** * Attempt to revoke a token. - * @param {*} dbCtx - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {*} dbCtx db context + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async _revokeToken(dbCtx, res, ctx) { const _scope = _fileScope('_revokeToken'); @@ -1039,10 +1043,10 @@ class Manager { /** * Legacy token validation flow. - * @param {*} dbCtx - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {*} dbCtx db context + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async _validateToken(dbCtx, req, res, ctx) { const _scope = _fileScope('_validateToken'); @@ -1075,9 +1079,9 @@ class Manager { /** * Given a list of newly-requested scopes, return a list of scopes * from previousScopes which are not in requestedScopes. - * @param {String[]} previousScopes - * @param {String[]} requestedScopes - * @returns {String[]} + * @param {string[]} previousScopes scopes + * @param {string[]} requestedScopes scopes + * @returns {string[]} scopes */ static _scopeDifference(previousScopes, requestedScopes) { const scopesToRemove = []; @@ -1095,10 +1099,10 @@ class Manager { /** * Redeem a refresh token for a new token. - * @param {*} dbCtx - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {*} dbCtx db context + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async _refreshToken(dbCtx, req, res, ctx) { const _scope = _fileScope('_refreshToken'); @@ -1192,15 +1196,15 @@ class Manager { /** * Generate a new ticket for later redemption. - * @param {Object} payload - * @param {} payload.subject deliver ticket to this endpoint - * @param {} payload.resource url the redeemed ticket is valid for accessing - * @param {String[]} payload.scopes list of scopes assigned to ticket - * @param {String} payload.identifier user generating ticket - * @param {} payload.profile profile of user generating ticket - * @param {Number} payload.ticketLifespanSeconds ticket redeemable for this long - * @returns {Promise} - */ + * @param {object} payload payload + * @param {string} payload.subject deliver ticket to this endpoint + * @param {string} payload.resource url the redeemed ticket is valid for accessing + * @param {string[]} payload.scopes list of scopes assigned to ticket + * @param {string} payload.identifier user generating ticket + * @param {string} payload.profile profile of user generating ticket + * @param {number} payload.ticketLifespanSeconds ticket redeemable for this long + * @returns {Promise} ticket + */ async _mintTicket({ subject, resource, scopes, identifier, profile, ticketLifespanSeconds }) { const _scope = _fileScope('_mintTicket'); this.logger.debug(_scope, 'called', { subject, resource, scopes, identifier, profile, ticketLifespanSeconds }); @@ -1221,19 +1225,19 @@ class Manager { /** * @typedef Ticket - * @property {String} codeId - * @property {Date} issued - * @property {Date} expires - * @property {URL} subject - * @property {URL} resource - * @property {String[]} scopes - * @property {String} identifier - * @property {URL} profile + * @property {string} codeId code id + * @property {Date} issued issued at + * @property {Date} expires expires at + * @property {URL} subject subject + * @property {URL} resource resource + * @property {string[]} scopes scopes + * @property {string} identifier identifier + * @property {URL} profile profile */ /** * - * @param {String} ticket - * @returns {Promise} + * @param {string} ticket ticket + * @returns {Promise} ticket object */ async _unpackTicket(ticket) { const ticketObj = await this.mysteryBox.unpack(ticket); @@ -1252,10 +1256,11 @@ class Manager { /** * Redeem a ticket for a token. - * @param {*} dbCtx - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {*} dbCtx db context + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context + * @returns {Promise} */ async _ticketAuthToken(dbCtx, req, res, ctx) { const _scope = _fileScope('_ticketAuthToken'); @@ -1310,10 +1315,10 @@ class Manager { /** * Redeem a code for a token. - * @param {*} dbCtx - * @param {http.ClientRequest} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {*} dbCtx db context + * @param {http.ClientRequest} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async _codeToken(dbCtx, req, res, ctx) { const _scope = _fileScope('_codeToken'); @@ -1393,9 +1398,9 @@ class Manager { /** * Issue, refresh, or validate a token. - * @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 postToken(req, res, ctx) { const _scope = _fileScope('postToken'); @@ -1451,9 +1456,10 @@ class Manager { * Ingest token from authorization header, setting ctx.bearer.isValid appropriately. * ctx.bearer not set if auth method not recognized. * This is for legacy validation on token endpoint. - * @param {*} dbCtx - * @param {http.ClientRequest} req - * @param {Object} ctx + * @param {*} dbCtx db context + * @param {http.ClientRequest} req request + * @param {object} ctx context + * @returns {Promise} */ async _checkTokenValidationRequest(dbCtx, req, ctx) { const _scope = _fileScope('_checkTokenValidationRequest'); @@ -1468,7 +1474,7 @@ class Manager { }; try { Object.assign(ctx.bearer, await this.mysteryBox.unpack(authString)); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.debug(_scope, 'failed to unpack token', { ctx }); Manager._setError(ctx, 'invalid_request', 'invalid token'); return; @@ -1509,9 +1515,9 @@ class Manager { /** * Accept an unsolicited ticket proffering. - * @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 postTicket(req, res, ctx) { const _scope = _fileScope('postTicket'); @@ -1528,14 +1534,14 @@ class Manager { if (iss) { try { new URL(iss); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.debug(_scope, 'unparsable issuer', { ticket, resource, subject, iss, ctx }); // continue, will try resource for metadata } } try { new URL(resource); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.debug(_scope, 'unparsable resource', { ticket, resource, subject, ctx }); throw new ResponseError(Enum.ErrorResponse.BadRequest); } @@ -1562,11 +1568,15 @@ class Manager { } + /** + * @typedef {object} AMQPChannel + * @property {Function} ack ack + */ /** * Process messages from proffered ticket queue. * Attempt to redeem ticket and publish to redeemed token queue. - * @param {AMQPChannel} channel - * @param {Buffer} message + * @param {AMQPChannel} channel channel + * @param {Buffer} message message */ async queuedTicketProcessor(channel, message) { const _scope = _fileScope('queuedTicketProcessor'); @@ -1601,7 +1611,7 @@ class Manager { let resourceUrlObj; try { resourceUrlObj = new URL(resource); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.error(_scope, 'unparsable resource, discarding', { payload }); channel.ack(message); return; @@ -1662,8 +1672,8 @@ class Manager { /** * Validate a token and return data about it. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async postIntrospection(res, ctx) { const _scope = _fileScope('postIntrospection'); @@ -1718,8 +1728,8 @@ class Manager { /** * Revoke a token or refresh token. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async postRevocation(res, ctx) { const _scope = _fileScope('postRevocation'); @@ -1740,8 +1750,8 @@ class Manager { /** * Profile information for a token. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async postUserInfo(res, ctx) { const _scope = _fileScope('postUserInfo'); @@ -1800,8 +1810,8 @@ class Manager { /** * Show admin interface, allowing manipulation of profiles and scopes. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getAdmin(res, ctx) { const _scope = _fileScope('getAdmin'); @@ -1822,8 +1832,8 @@ class Manager { /** * Process admin interface events. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async postAdmin(res, ctx) { const _scope = _fileScope('postAdmin'); @@ -1952,8 +1962,8 @@ class Manager { /** * Show ticket proffer interface. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getAdminTicket(res, ctx) { const _scope = _fileScope('getAdminTicket'); @@ -1975,8 +1985,8 @@ class Manager { /** * Handle ticket proffer interface submission. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async postAdminTicket(res, ctx) { const _scope = _fileScope('postAdminTicket'); @@ -1992,7 +2002,7 @@ class Manager { ].forEach((param) => { try { ctx[param.ctxProp] = new URL(ctx.parsedBody[param.bodyParam]); - } catch (e) { + } catch (e) { // eslint-disable-line no-unused-vars this.logger.debug(_scope, `invalid ${param.bodyParam}`, { ctx }); ctx.errors.push(param.err); } @@ -2087,8 +2097,8 @@ class Manager { /** * Report on generally uninteresting backend information. * Also allow a few event invocations. - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getAdminMaintenance(res, ctx) { const _scope = _fileScope('getAdminMaintenance'); @@ -2125,8 +2135,8 @@ class Manager { /** * - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async getHealthcheck(res, ctx) { const _scope = _fileScope('getHealthcheck'); diff --git a/src/service.js b/src/service.js index dc131c3..f3b7be0 100644 --- a/src/service.js +++ b/src/service.js @@ -9,14 +9,17 @@ const path = require('path'); const { Dingus } = require('@squeep/api-dingus'); const common = require('./common'); const Manager = require('./manager'); -const { Authenticator, SessionManager } = require('@squeep/authentication-module'); -const { ResourceAuthenticator } = require('@squeep/resource-authentication-module'); +const { Authenticator, ResourceAuthenticator, SessionManager } = require('@squeep/authentication-module'); const { initContext, navLinks } = require('./template/template-helper'); const Enum = require('./enum'); const { ResponseError } = require('./errors'); const _fileScope = common.fileScope(__filename); +/** + * @typedef {import('node:http')} http + */ + class Service extends Dingus { constructor(logger, db, options, asyncLocalStorage) { super(logger, { @@ -103,9 +106,9 @@ class Service extends Dingus { /** * Do a little more on each request. - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async preHandler(req, res, ctx) { const _scope = _fileScope('preHandler'); @@ -125,9 +128,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminLogin(req, res, ctx) { const _scope = _fileScope('handlerGetAdminLogin'); @@ -142,9 +145,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostAdminLogin(req, res, ctx) { const _scope = _fileScope('handlerPostAdminLogin'); @@ -163,9 +166,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminSettings(req, res, ctx) { const _scope = _fileScope('handlerGetAdminSettings'); @@ -182,9 +185,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostAdminSettings(req, res, ctx) { const _scope = _fileScope('handlerPostAdminSettings'); @@ -202,9 +205,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminLogout(req, res, ctx) { const _scope = _fileScope('handlerGetAdminLogout'); @@ -221,9 +224,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdmin(req, res, ctx) { const _scope = _fileScope('handlerGetAdmin'); @@ -240,9 +243,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostAdmin(req, res, ctx) { const _scope = _fileScope('handlerPostAdmin'); @@ -260,9 +263,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminTicket(req, res, ctx) { const _scope = _fileScope('handlerGetAdminTicket'); @@ -279,9 +282,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostAdminTicket(req, res, ctx) { const _scope = _fileScope('handlerPostAdminTicket'); @@ -299,9 +302,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetMeta(req, res, ctx) { const _scope = _fileScope('handlerGetMeta'); @@ -321,9 +324,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAuthorization(req, res, ctx) { const _scope = _fileScope('handlerGetAuthorization'); @@ -340,9 +343,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostAuthorization(req, res, ctx) { const _scope = _fileScope('handlerPostAuthorization'); @@ -364,9 +367,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostConsent(req, res, ctx) { const _scope = _fileScope('handlerPostConsent'); @@ -386,9 +389,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostTicket(req, res, ctx) { const _scope = _fileScope('handlerPostTicket'); @@ -408,9 +411,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostToken(req, res, ctx) { const _scope = _fileScope('handlerPostToken'); @@ -430,9 +433,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostRevocation(req, res, ctx) { const _scope = _fileScope('handlerPostRevocation'); @@ -452,9 +455,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostIntrospection(req, res, ctx) { const _scope = _fileScope('handlerPostIntrospection'); @@ -476,9 +479,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerPostUserInfo(req, res, ctx) { const _scope = _fileScope('handlerPostUserInfo'); @@ -498,9 +501,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetRoot(req, res, ctx) { const _scope = _fileScope('handlerGetRoot'); @@ -521,6 +524,9 @@ class Service extends Dingus { /** * Temporary to see what an unsolicited payload contains. + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerWhaGwan(req, res, ctx) { this.setResponseType(this.responseTypes, req, res, ctx); @@ -529,9 +535,9 @@ class Service extends Dingus { } /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetHealthcheck(req, res, ctx) { const _scope = _fileScope('handlerGetHealthcheck'); @@ -544,9 +550,9 @@ class Service extends Dingus { /** - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerGetAdminMaintenance(req, res, ctx) { const _scope = _fileScope('handlerGetAdminMaintenance'); @@ -567,9 +573,9 @@ class Service extends Dingus { * Intercept this and redirect if we have enough information, otherwise default to framework. * Fixing this will likely have to wait until an e2e test framework is in place. * The redirect attempt should probably be contained in a Manager method, but here it is for now. - * @param {http.IncomingMessage} req - * @param {http.ServerResponse} res - * @param {Object} ctx + * @param {http.IncomingMessage} req request + * @param {http.ServerResponse} res response + * @param {object} ctx context */ async handlerInternalServerError(req, res, ctx) { const _scope = _fileScope('handlerInternalServerError'); diff --git a/src/template/admin-html.js b/src/template/admin-html.js index 3b16a28..f72102f 100644 --- a/src/template/admin-html.js +++ b/src/template/admin-html.js @@ -10,11 +10,23 @@ const th = require('./template-helper'); const { sessionNavLinks } = require('@squeep/authentication-module'); +/** + * + * @param {string} profile profile + * @returns {string} li + */ function renderProfileLI(profile) { return `\t
  • ${profile}
  • `; } +/** + * + * @param {string} profile profile + * @param {string} scope scope + * @param {boolean} selected is selected + * @returns {string} td + */ function renderProfileScopeIndicator(profile, scope, selected) { const checked = selected ? ' checked' : ''; return `\t\t @@ -22,6 +34,13 @@ function renderProfileScopeIndicator(profile, scope, selected) { \t\t`; } +/** + * + * @param {string} scope scope + * @param {object} details details + * @param {string[]} profiles profiles + * @returns {string} tr + */ function renderScopeRow(scope, details, profiles) { return `\t ${(profiles || []).map((profile) => renderProfileScopeIndicator(profile, scope, details.profiles.includes(profile))).join('\n')} @@ -37,6 +56,11 @@ ${(profiles || []).map((profile) => renderProfileScopeIndicator(profile, scope, } +/** + * + * @param {string} profile profile + * @returns {string} th + */ function renderProfileHeader(profile) { return ` \t\t${profile} @@ -44,6 +68,12 @@ function renderProfileHeader(profile) { } +/** + * + * @param {object} scopeIndex scopes + * @param {string[]} profiles profiles + * @returns {string} table + */ function scopeIndexTable(scopeIndex, profiles) { return ` @@ -61,6 +91,11 @@ ${Object.entries(scopeIndex).sort(th.scopeCompare).map(([scope, details]) => ren
    `; } +/** + * + * @param {object} token token + * @returns {string} type + */ function _tokenType(token) { if (token.resource) { return 'ticket-token'; @@ -71,6 +106,11 @@ function _tokenType(token) { return 'token'; } +/** + * + * @param {object} token token + * @returns {string} tr + */ function renderTokenRow(token) { const createdTitle = token.refreshed ? 'Refreshed At' : 'Created At'; const createdDate = token.refreshed ? token.refreshed : token.created; @@ -91,12 +131,20 @@ function renderTokenRow(token) { \t\t`; } +/** + * @returns {string} tr + */ function noTokensRows() { return [`\t\t \t\t\t(No active or recent tokens.) \t\t`]; } +/** + * + * @param {object} tokens tokens + * @returns {string} table + */ function tokenTable(tokens) { const tokenRows = tokens?.length ? tokens.map((token) => renderTokenRow(token)) : noTokensRows(); const formOpen = tokens?.length ? '
    \n' : ''; @@ -122,6 +170,11 @@ ${tokenRows.join('\n')} ${formClose}`; } +/** + * + * @param {object} ctx context + * @returns {string} section + */ function mainContent(ctx) { const profileList = (ctx.profilesScopes?.profiles || []).map((p) => renderProfileLI(p)).join('\n'); return `
    @@ -186,16 +239,16 @@ ${tokenTable(ctx.tokens)} /** * - * @param {Object} ctx - * @param {Object} ctx.profilesScopes.scopeIndex - * @param {String[]} ctx.profilesScopes.profiles - * @param {Object[]} ctx.tokens - * @param {Object} options - * @param {Object} options.manager - * @param {String} options.manager.pageTitle - * @param {String} options.manager.logoUrl - * @param {String[]} options.manager.footerEntries - * @returns {String} + * @param {object} ctx context + * @param {object} ctx.profilesScopes.scopeIndex scopes + * @param {string[]} ctx.profilesScopes.profiles profiles + * @param {object[]} ctx.tokens tokens + * @param {object} options options + * @param {object} options.manager manager options + * @param {string} options.manager.pageTitle page title + * @param {string} options.manager.logoUrl logo url + * @param {string[]} options.manager.footerEntries footer entries + * @returns {string} page */ module.exports = (ctx, options) => { const pagePathLevel = 1; diff --git a/src/template/admin-maintenance-html.js b/src/template/admin-maintenance-html.js index 764b4d3..0f4de44 100644 --- a/src/template/admin-maintenance-html.js +++ b/src/template/admin-maintenance-html.js @@ -3,6 +3,11 @@ const th = require('./template-helper'); const { sessionNavLinks } = require('@squeep/authentication-module'); +/** + * + * @param {object} entry entry + * @returns {string} tr + */ function renderAlmanacRow(entry) { const { event, date } = entry; return ` @@ -11,6 +16,11 @@ function renderAlmanacRow(entry) { `; } +/** + * + * @param {object[]} almanac entries + * @returns {string} section + */ function almanacSection(almanac) { return `
    \t

    Almanac

    @@ -28,6 +38,12 @@ ${almanac.map((entry) => renderAlmanacRow(entry)).join('\n')}
    `; } +/** + * + * @param {string} choreName name + * @param {object} choreDetails details + * @returns {string} tr + */ function renderChoreRow(choreName, choreDetails) { const { intervalMs, nextSchedule } = choreDetails; return ` @@ -37,6 +53,11 @@ function renderChoreRow(choreName, choreDetails) { `; } +/** + * + * @param {object} chores chores + * @returns {string} section + */ function choresSection(chores) { return `
    \t

    Chores

    @@ -57,15 +78,14 @@ ${Object.entries(chores).map((chore) => renderChoreRow(...chore)).join('\n')} /** * - * @param {Object} ctx - * @param {Object[]} ctx.almanac - * @param {Object} ctx.chores - * @param {Object} options - * @param {Object} options.manager - * @param {String} options.manager.pageTitle - * @param {String[]} options.manager.footerEntries - * @param {String} options.adminContactHTML - * @returns {String} + * @param {object} ctx context + * @param {object[]} ctx.almanac entries + * @param {object} ctx.chores chores + * @param {object} options options + * @param {object} options.manager manager options + * @param {string} options.manager.pageTitle page title + * @param {string[]} options.manager.footerEntries footer entires + * @returns {string} page */ module.exports = (ctx, options) => { const pagePathLevel = 1; diff --git a/src/template/admin-ticket-html.js b/src/template/admin-ticket-html.js index a0475ad..75d7ce7 100644 --- a/src/template/admin-ticket-html.js +++ b/src/template/admin-ticket-html.js @@ -8,10 +8,20 @@ const th = require('./template-helper'); const { sessionNavLinks } = require('@squeep/authentication-module'); +/** + * + * @param {string} profile profile + * @returns {string} option + */ function renderProfileOption(profile) { return ``; } +/** + * + * @param {string} scope scope + * @returns {string} tr + */ function renderScopeCheckboxTR(scope) { const defaultChecked = ['read']; const checked = defaultChecked.includes(scope) ? ' checked' : ''; @@ -21,6 +31,11 @@ function renderScopeCheckboxTR(scope) { `; } +/** + * + * @param {object} ctx context + * @returns {string} section + */ function mainContent(ctx) { const profileOptions = th.indented(4, (ctx?.profilesScopes?.profiles || []).map((profile) => renderProfileOption(profile))) .join('\n'); @@ -71,20 +86,20 @@ ${scopesCheckboxRows} /** * - * @param {Object} ctx - * @param {Object} ctx.profilesScopes.scopeIndex - * @param {String[]} ctx.profileScopes.profiles - * @param {Object} options - * @param {Object} options.manager - * @param {String} options.manager.pageTitle - * @param {String} options.manager.logoUrl - * @param {String[]} options.manager.footerEntries - * @returns {String} + * @param {object} ctx context + * @param {object} ctx.profilesScopes.scopeIndex scopes structure + * @param {string[]} ctx.profileScopes.profiles profile + * @param {object} options options + * @param {object} options.manager manager options + * @param {string} options.manager.pageTitle page title + * @param {string} options.manager.logoUrl logo url + * @param {string[]} options.manager.footerEntries footer entries + * @returns {string} page */ module.exports = (ctx, options) => { const pagePathLevel = 1; const htmlOptions = { - padeIdentifier: 'ticketProffer', + pageIdentifier: 'ticketProffer', pageTitle: options.manager.pageTitle + ' - Ticket Proffer', logoUrl: options.manager.logoUrl, footerEntries: options.manager.footerEntries, diff --git a/src/template/authorization-error-html.js b/src/template/authorization-error-html.js index 16e3c48..83d9526 100644 --- a/src/template/authorization-error-html.js +++ b/src/template/authorization-error-html.js @@ -5,15 +5,15 @@ const { sessionNavLinks } = require('@squeep/authentication-module'); /** * - * @param {Object} ctx - * @param {Object} ctx.session - * @param {String=} ctx.session.error - * @param {String[]=} ctx.session.errorDescriptions - * @param {Object} options - * @param {Object} options.manager - * @param {String} options.manager.pageTitle - * @param {String} options.manager.footerEntries - * @returns {String} + * @param {object} ctx context + * @param {object} ctx.session session + * @param {string=} ctx.session.error errors + * @param {string[]=} ctx.session.errorDescriptions errors + * @param {object} options options + * @param {object} options.manager manager options + * @param {string} options.manager.pageTitle page title + * @param {string} options.manager.footerEntries footer entries + * @returns {string} page */ module.exports = (ctx, options) => { const pagePathLevel = 0; diff --git a/src/template/authorization-request-html.js b/src/template/authorization-request-html.js index ac2ea06..b23fb92 100644 --- a/src/template/authorization-request-html.js +++ b/src/template/authorization-request-html.js @@ -4,13 +4,13 @@ const th = require('./template-helper'); const { sessionNavLinks } = require('@squeep/authentication-module'); /** - * @param {Object} hApp - * @param {Object} hApp.properties - * @param {String[]=} hApp.properties.url - * @param {String[]=} hApp.properties.summary - * @param {String[]=} hApp.properties.logo - * @param {String[]=} hApp.properties.name - * @returns {String} + * @param {object} hApp client identifier h-app + * @param {object} hApp.properties properties + * @param {string[]=} hApp.properties.url url + * @param {string[]=} hApp.properties.summary summary + * @param {string[]=} hApp.properties.logo logo + * @param {string[]=} hApp.properties.name name + * @returns {string} span */ function renderClientIdentifierProperties(hApp) { const properties = hApp.properties || {}; @@ -47,9 +47,9 @@ function renderClientIdentifierProperties(hApp) { /** - * @param {Object} clientIdentifier - * @param {Object[]} clientIdentifier.items - * @returns {String} + * @param {object} clientIdentifier client identifier + * @param {object[]} clientIdentifier.items items + * @returns {string} spans */ function renderClientIdentifier(clientIdentifier) { const hAppEntries = clientIdentifier?.items || []; @@ -58,9 +58,9 @@ function renderClientIdentifier(clientIdentifier) { /** - * @param {String} profile - * @param {Boolean} selected - * @returns {String} + * @param {string} profile profile + * @param {boolean} selected is selected + * @returns {string} option */ function renderProfileOption(profile, selected) { return ``; @@ -68,9 +68,9 @@ function renderProfileOption(profile, selected) { /** - * @param {String[]} availableProfiles - * @param {String} hintProfile - * @returns {String} + * @param {string[]} availableProfiles profiles + * @param {string} hintProfile profile + * @returns {string} fieldset */ function renderProfileFieldset(availableProfiles, hintProfile) { if (!availableProfiles || availableProfiles.length <= 1) { @@ -93,12 +93,16 @@ ${availableProfiles.map((profile) => renderProfileOption(profile, profile === hi /** - * @param {ScopeDetails} scope - * @param {String} scope.scope - * @param {String} scope.description - * @param {String[]} scope.profiles - * @param {Boolean} checked - * @returns {String} + * @typedef {object} ScopeDetails + * @property {string} scope scope + * @property {string} description description + * @property {string[]} profiles profiles + */ + +/** + * @param {ScopeDetails} scope scope details + * @param {boolean} checked is checked + * @returns {string} scope li */ function renderScopeCheckboxLI(scope, checked) { let scopeDescription; @@ -122,6 +126,11 @@ function renderScopeCheckboxLI(scope, checked) { } +/** + * + * @param {ScopeDetails[]=} requestedScopes scope details + * @returns {string} fieldset + */ function renderRequestedScopes(requestedScopes) { if (!requestedScopes?.length) { return ''; @@ -140,8 +149,8 @@ ${requestedScopes.map((scopeDetails) => renderScopeCheckboxLI(scopeDetails, true } /** - * @param {ScopeDetails[]} additionalScopes - * @returns {String} + * @param {ScopeDetails[]} additionalScopes scopes + * @returns {string} fieldset */ function renderAdditionalScopes(additionalScopes) { const parts = []; @@ -173,6 +182,8 @@ ${additionalScopes.map((scopeDetails) => renderScopeCheckboxLI(scopeDetails, fal /** * + * @param {string[]} requestedScopes scopes + * @returns {string} fieldset */ function renderExpiration(requestedScopes) { const tokenableScopes = requestedScopes.filter((s) => !['profile', 'email'].includes(s)); @@ -215,6 +226,15 @@ function renderExpiration(requestedScopes) { \t`; } +/** + * + * @param {string} name name + * @param {string} value value + * @param {string} label label + * @param {boolean} checked is checked + * @param {number} indent indent + * @returns {string} div + */ function radioButton(name, value, label, checked = false, indent = 0) { const id = `${name}-${value}`; return th.indented(indent, [ @@ -225,27 +245,31 @@ function radioButton(name, value, label, checked = false, indent = 0) { ]).join(''); } +/** + * @alias {object} ScopeIndex + */ + /** * - * @param {Object} ctx - * @param {Object[]} ctx.notifications - * @param {Object} ctx.session - * @param {String[]=} ctx.session.scope - * @param {URL=} ctx.session.me - * @param {String[]} ctx.session.profiles - * @param {ScopeIndex} ctx.session.scopeIndex - * @param {Object} ctx.session.clientIdentifier - * @param {Object[]} ctx.session.clientIdentifier.items - * @param {Object} ctx.session.clientIdentifier.items.properties - * @param {String[]=} ctx.session.clientIdentifier.items.properties.url - * @param {String[]=} ctx.session.clientIdentifier.items.properties.summary - * @param {String[]=} ctx.session.clientIdentifier.items.properties.logo - * @param {String[]=} ctx.session.clientIdentifier.items.properties.name - * @param {String} ctx.session.clientId - * @param {String} ctx.session.persist - * @param {String} ctx.session.redirectUri - * @param {Object} options - * @returns {String} + * @param {object} ctx context + * @param {object[]} ctx.notifications notifications + * @param {object} ctx.session session + * @param {string[]=} ctx.session.scope scopes + * @param {URL=} ctx.session.me profile + * @param {string[]} ctx.session.profiles profiles + * @param {ScopeIndex} ctx.session.scopeIndex scopes structure + * @param {object} ctx.session.clientIdentifier client identifier + * @param {object[]} ctx.session.clientIdentifier.items items + * @param {object} ctx.session.clientIdentifier.items.properties properties + * @param {string[]=} ctx.session.clientIdentifier.items.properties.url url + * @param {string[]=} ctx.session.clientIdentifier.items.properties.summary sumamry + * @param {string[]=} ctx.session.clientIdentifier.items.properties.logo logo + * @param {string[]=} ctx.session.clientIdentifier.items.properties.name name + * @param {string} ctx.session.clientId client id + * @param {string} ctx.session.persist persist + * @param {string} ctx.session.redirectUri redirect + * @param {object} options options + * @returns {string} section */ function mainContent(ctx, options) { // eslint-disable-line no-unused-vars const session = ctx.session || {}; @@ -283,7 +307,7 @@ function mainContent(ctx, options) { // eslint-disable-line no-unused-vars return [ `
    -\tThe application client ${renderClientIdentifier(session.clientIdentifier)} at ${session.clientId} would like to identify you as ${hintedProfile ? hintedProfile : '(unspecified)'}. +\tThe application client ${renderClientIdentifier(session.clientIdentifier)} at ${session.clientId} would like to identify you as ${hintedProfile || '(unspecified)'}.
    \t`, @@ -310,21 +334,21 @@ function mainContent(ctx, options) { // eslint-disable-line no-unused-vars /** * - * @param {Object} ctx - * @param {Object} ctx.session - * @param {String[]=} ctx.session.scope - * @param {URL=} ctx.session.me - * @param {String[]} ctx.session.profiles - * @param {ScopeIndex} ctx.session.scopeIndex - * @param {Object} ctx.session.clientIdentifier - * @param {String} ctx.session.clientId - * @param {String} ctx.session.persist - * @param {String} ctx.session.redirectUri - * @param {Object} options - * @param {Object} options.manager - * @param {String} options.manager.pageTitle - * @param {String} options.manager.footerEntries - * @returns {String} + * @param {object} ctx context + * @param {object} ctx.session session object + * @param {string[]=} ctx.session.scope scopes + * @param {URL=} ctx.session.me url + * @param {string[]} ctx.session.profiles profiles + * @param {ScopeIndex} ctx.session.scopeIndex scopes structure + * @param {object} ctx.session.clientIdentifier client identifier + * @param {string} ctx.session.clientId client id + * @param {string} ctx.session.persist persist + * @param {string} ctx.session.redirectUri redirect url + * @param {object} options options + * @param {object} options.manager manager options + * @param {string} options.manager.pageTitle page title + * @param {string} options.manager.footerEntries footer entries + * @returns {string} page */ module.exports = (ctx, options) => { const pagePathLevel = 0; diff --git a/src/template/root-html.js b/src/template/root-html.js index 2b7abfe..c6095dc 100644 --- a/src/template/root-html.js +++ b/src/template/root-html.js @@ -3,6 +3,9 @@ const th = require('./template-helper'); const { sessionNavLinks } = require('@squeep/authentication-module'); +/** + * @returns {string} section + */ function aboutSection() { return `
    @@ -19,6 +22,10 @@ function aboutSection() {
    `; } +/** + * @param {string} contactHTML content + * @returns {string} section + */ function contactSection(contactHTML) { let section = ''; if (contactHTML) { @@ -31,13 +38,13 @@ ${contactHTML} /** * - * @param {Object} ctx - * @param {Object} options - * @param {Object} options.manager - * @param {String} options.manager.pageTitle - * @param {String[]} options.manager.footerEntries - * @param {String} options.adminContactHTML - * @returns {String} + * @param {object} ctx context + * @param {object} options options + * @param {object} options.manager manager options + * @param {string} options.manager.pageTitle page title + * @param {string[]} options.manager.footerEntries footer entries + * @param {string=} options.adminContactHTML content + * @returns {string} page */ module.exports = (ctx, options) => { const pagePathLevel = 0; diff --git a/src/template/template-helper.js b/src/template/template-helper.js index f15d3e6..4c0ad9d 100644 --- a/src/template/template-helper.js +++ b/src/template/template-helper.js @@ -5,8 +5,8 @@ const { TemplateHelper } = require('@squeep/html-template-helper'); /** * Escape a string to be suitable as a CSS name. - * @param {String} unsafeName - * @returns {String} + * @param {string} unsafeName unsafe name + * @returns {string} escaped name */ function escapeCSS(unsafeName) { return unsafeName.replace(/([^0-9a-zA-Z-])/g, '\\$1'); @@ -18,9 +18,9 @@ function escapeCSS(unsafeName) { * return the comparison between the two, for sorting. * Scopes are sorted such that they are grouped by application, then name. * Empty applications are sorted ahead of extant applications. - * @param {Array} a - * @param {Array} b - * @returns {Number} + * @param {[string, object]} a [scopeName, scopeDetails] + * @param {[string, object]} b [scopeName, scopeDetails] + * @returns {number} comparison */ function scopeCompare([aScope, aDetails], [bScope, bDetails]) { const { application: aApp } = aDetails; @@ -49,9 +49,9 @@ function scopeCompare([aScope, aDetails], [bScope, bDetails]) { /** * Populate common navLinks for page templates. - * @param {Number} pagePathLevel - * @param {Object} ctx - * @param {Object} options + * @param {number} pagePathLevel depth from root + * @param {object} ctx context + * @param {object} options options */ function navLinks(pagePathLevel, ctx, options) { if (!options.navLinks) { diff --git a/test/src/chores.js b/test/src/chores.js index 0272990..1656088 100644 --- a/test/src/chores.js +++ b/test/src/chores.js @@ -1,5 +1,3 @@ -/* eslint-env mocha */ -/* eslint-disable node/no-unpublished-require */ 'use strict'; const assert = require('assert'); diff --git a/test/src/common.js b/test/src/common.js index 36b8419..3335147 100644 --- a/test/src/common.js +++ b/test/src/common.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ 'use strict'; const assert = require('assert'); diff --git a/test/src/db/abstract.js b/test/src/db/abstract.js index bf74e97..a830a3e 100644 --- a/test/src/db/abstract.js +++ b/test/src/db/abstract.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 sinon = require('sinon'); const StubDatabase = require('../../stub-db'); const StubLogger = require('../../stub-logger'); diff --git a/test/src/db/factory.js b/test/src/db/factory.js index 31fdd8d..ff9e1c2 100644 --- a/test/src/db/factory.js +++ b/test/src/db/factory.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 sinon = require('sinon'); const Logger = require('@squeep/logger-json-console'); const DB = require('../../../src/db'); const DBErrors = require('../../../src/db/errors'); diff --git a/test/src/db/integration.js b/test/src/db/integration.js index 10e88df..b81d06b 100644 --- a/test/src/db/integration.js +++ b/test/src/db/integration.js @@ -1,5 +1,4 @@ -/* eslint-env mocha */ -/* eslint-disable sonarjs/no-identical-functions */ +/* eslint-disable security/detect-object-injection */ 'use strict'; /** @@ -17,10 +16,8 @@ */ const assert = require('assert'); -const { step } = require('mocha-steps'); // eslint-disable-line node/no-unpublished-require +const { step } = require('mocha-steps'); const StubLogger = require('../../stub-logger'); -// const DBErrors = require('../../../src/db/errors'); -// const testData = require('../../test-data/db-integration'); describe('Database Integration', function () { const implementations = []; diff --git a/test/src/db/postgres.js b/test/src/db/postgres.js index c00daad..b617c1d 100644 --- a/test/src/db/postgres.js +++ b/test/src/db/postgres.js @@ -1,12 +1,9 @@ -/* 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'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const sinon = require('sinon'); const StubLogger = require('../../stub-logger'); const StubDatabase = require('../../stub-db'); const DB = require('../../../src/db/postgres'); @@ -281,7 +278,7 @@ describe('DatabasePostgres', function () { assert(db.db.batch.called); }); it('failure', async function () { - sinon.stub(db.db, 'tx').rejects(expectedException) + sinon.stub(db.db, 'tx').rejects(expectedException); await assert.rejects(() => db._purgeTables(true), expectedException); }); }); // _purgeTables @@ -318,7 +315,7 @@ describe('DatabasePostgres', function () { let event, date; beforeEach(function () { event = 'test_event'; - date = new Date('Fri Dec 22 03:27 UTC 2023') + date = new Date('Fri Dec 22 03:27 UTC 2023'); }); it('success', async function () { const dbResult = { @@ -823,7 +820,7 @@ describe('DatabasePostgres', function () { duration: 22, }; sinon.stub(db.db, 'result').resolves(dbResult); - await db.resourceUpsert(dbCtx, resourceId, secret, description) + await db.resourceUpsert(dbCtx, resourceId, secret, description); }); it('failure', async function () { const dbResult = { diff --git a/test/src/db/schema-version-helper.js b/test/src/db/schema-version-helper.js index cc876d4..2859d30 100644 --- a/test/src/db/schema-version-helper.js +++ b/test/src/db/schema-version-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 sinon = require('sinon'); const fs = require('fs'); const svh = require('../../../src/db/schema-version-helper'); @@ -121,6 +120,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); }); @@ -151,9 +151,10 @@ 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); }); }); // unappliedSchemaVersions -}); \ No newline at end of file +}); diff --git a/test/src/db/sqlite.js b/test/src/db/sqlite.js index f2d9546..b0eeace 100644 --- a/test/src/db/sqlite.js +++ b/test/src/db/sqlite.js @@ -1,12 +1,9 @@ -/* 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'); -const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require +const sinon = require('sinon'); const StubDatabase = require('../../stub-db'); const StubLogger = require('../../stub-logger'); const DB = require('../../../src/db/sqlite'); @@ -112,7 +109,7 @@ describe('DatabaseSQLite', function () { db._optimize(); assert(db.db.pragma.called); assert(db.statement._optimize.all.called); - assert.strictEqual(db.changesSinceLastOptimize, 0n) + assert.strictEqual(db.changesSinceLastOptimize, 0n); }); }); // _optimize @@ -220,7 +217,7 @@ describe('DatabaseSQLite', function () { let event, date, dbResult; beforeEach(function () { event = 'test_event'; - date = new Date('Fri Dec 22 03:27 UTC 2023') + date = new Date('Fri Dec 22 03:27 UTC 2023'); sinon.stub(db.statement.almanacUpsert, 'run'); dbResult = { changes: 1, @@ -574,7 +571,7 @@ describe('DatabaseSQLite', function () { expires: new Date(refreshResponse.expires * 1000), refreshExpires: new Date(refreshResponse.refreshExpires * 1000), scopes: ['blah'], - } + }; const response = db.refreshCode(dbCtx, codeId, refreshed, removeScopes); assert.deepStrictEqual(response, expectedResponse); }); @@ -584,7 +581,7 @@ describe('DatabaseSQLite', function () { const expectedResponse = { expires: new Date(refreshResponse.expires * 1000), refreshExpires: new Date(refreshResponse.refreshExpires * 1000), - } + }; removeScopes = []; const response = db.refreshCode(dbCtx, codeId, refreshed, removeScopes); assert.deepStrictEqual(response, expectedResponse); @@ -596,7 +593,7 @@ describe('DatabaseSQLite', function () { expires: new Date(refreshResponse.expires * 1000), refreshExpires: new Date(refreshResponse.refreshExpires * 1000), scopes: [], - } + }; const response = db.refreshCode(dbCtx, codeId, refreshed, removeScopes); assert.deepStrictEqual(response, expectedResponse); }); @@ -723,7 +720,7 @@ describe('DatabaseSQLite', function () { sinon.stub(db.statement.scopeInUse, 'get'); dbGetResult = { inUse: false, - } + }; sinon.stub(db.statement.scopeDelete, 'run'); dbRunResult = { changes: 1, @@ -898,7 +895,7 @@ describe('DatabaseSQLite', function () { let dbResult, codeId; beforeEach(function () { codeId = '2f226616-3e79-11ec-ad0f-0025905f714a'; - sinon.stub(db.statement.tokenRevokeByCodeId, 'run') + sinon.stub(db.statement.tokenRevokeByCodeId, 'run'); dbResult = { changes: 1, lastInsertRowid: undefined, @@ -1049,7 +1046,7 @@ describe('DatabaseSQLite', function () { const dbResultAlmanac = { ...dbResult, changes: 0, - } + }; db.statement.ticketTokenPublished.run.returns(dbResult); db.statement.almanacUpsert.run.returns(dbResultAlmanac); assert.throws(() => db.ticketTokenPublished(dbCtx, redeemedData), DBErrors.UnexpectedResult); diff --git a/test/src/errors.js b/test/src/errors.js index 509f3b1..1e3dca4 100644 --- a/test/src/errors.js +++ b/test/src/errors.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ 'use strict'; const assert = require('assert'); diff --git a/test/src/logger.js b/test/src/logger.js index cb5914b..1142a13 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 sinon = require('sinon'); const Logger = require('../../src/logger'); const Config = require('../../config'); @@ -70,7 +69,7 @@ describe('Logger', function () { otpConfirmKey: '1234567890123456789012', otpConfirmBox: 'xxxMysteryxxx', otpState: 'xxxMysteryxxx', - } + }, }); assert(logger.backend.info.called); assert(!logger.backend.info.args[0][0].includes('"1234567890123456789012"')); diff --git a/test/src/manager.js b/test/src/manager.js index 66e6f59..54e867f 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 sinon = require('sinon'); const Manager = require('../../src/manager'); const Config = require('../../config'); @@ -1558,13 +1555,13 @@ describe('Manager', function () { manager.mysteryBox.unpack.resolves({}); req.getHeader.returns('Bearer XXX'); await manager._checkTokenValidationRequest(dbCtx, req, ctx); - assert(ctx.session.error) + assert(ctx.session.error); }); it('covers no token', async function () { manager.mysteryBox.unpack.resolves({ c: 'xxx' }); req.getHeader.returns('Bearer XXX'); await manager._checkTokenValidationRequest(dbCtx, req, ctx); - assert(ctx.session.error) + assert(ctx.session.error); }); it('covers db error', async function () { manager.mysteryBox.unpack.resolves({ c: 'xxx' }); diff --git a/test/src/service.js b/test/src/service.js index e555029..55cfec2 100644 --- a/test/src/service.js +++ b/test/src/service.js @@ -1,10 +1,7 @@ -/* 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 sinon = require('sinon'); const { AsyncLocalStorage } = require('node:async_hooks'); const StubDb = require('../stub-db'); @@ -323,4 +320,4 @@ describe('Service', function () { }); }); // handlerWhaGwan -}); \ No newline at end of file +}); diff --git a/test/src/template/admin-html.js b/test/src/template/admin-html.js index 8f5a6c2..0512807 100644 --- a/test/src/template/admin-html.js +++ b/test/src/template/admin-html.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ 'use strict'; const assert = require('assert'); diff --git a/test/src/template/admin-maintenance-html.js b/test/src/template/admin-maintenance-html.js index e0dea09..dbe90c9 100644 --- a/test/src/template/admin-maintenance-html.js +++ b/test/src/template/admin-maintenance-html.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ 'use strict'; const assert = require('assert'); diff --git a/test/src/template/admin-ticket-html.js b/test/src/template/admin-ticket-html.js index d5eb28f..6bad7b4 100644 --- a/test/src/template/admin-ticket-html.js +++ b/test/src/template/admin-ticket-html.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ 'use strict'; const assert = require('assert'); diff --git a/test/src/template/authorization-error-html.js b/test/src/template/authorization-error-html.js index 4858b51..6a30d96 100644 --- a/test/src/template/authorization-error-html.js +++ b/test/src/template/authorization-error-html.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ 'use strict'; const assert = require('assert'); @@ -27,7 +26,7 @@ describe('Authorization Error HTML Template', function () { ctx.session = { error: 'error_name', errorDescriptions: ['something went wrong', 'another thing went wrong'], - } + }; const result = template(ctx, config); await lintHtml(result); assert(result); diff --git a/test/src/template/authorization-request-html.js b/test/src/template/authorization-request-html.js index cefefef..590dcf6 100644 --- a/test/src/template/authorization-request-html.js +++ b/test/src/template/authorization-request-html.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ 'use strict'; const assert = require('assert'); diff --git a/test/src/template/root-html.js b/test/src/template/root-html.js index b141bb1..6ac011a 100644 --- a/test/src/template/root-html.js +++ b/test/src/template/root-html.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ 'use strict'; const assert = require('assert'); diff --git a/test/src/template/template-helper.js b/test/src/template/template-helper.js index a40293e..ca61f34 100644 --- a/test/src/template/template-helper.js +++ b/test/src/template/template-helper.js @@ -1,4 +1,3 @@ -/* eslint-env mocha */ 'use strict'; const assert = require('assert'); diff --git a/test/stub-db.js b/test/stub-db.js index 054cc47..3efc125 100644 --- a/test/stub-db.js +++ b/test/stub-db.js @@ -1,9 +1,13 @@ -/* eslint-disable security/detect-object-injection */ 'use strict'; -const { StubDatabase: Base } = require('@squeep/test-helper'); // eslint-disable-line node/no-unpublished-require +const { StubDatabase: Base } = require('@squeep/test-helper'); +const sinon = require('sinon'); class StubDatabase extends Base { + constructor() { + super(sinon); + } + get _stubFns() { return [ ...super._stubFns, diff --git a/test/stub-logger.js b/test/stub-logger.js index 8be142f..5aa88c3 100644 --- a/test/stub-logger.js +++ b/test/stub-logger.js @@ -1,10 +1,13 @@ 'use strict'; -const { StubLogger: Base } = require('@squeep/test-helper'); // eslint-disable-line node/no-unpublished-require +const { StubLogger: Base } = require('@squeep/test-helper'); +const sinon = require('sinon'); class StubLogger extends Base { - + constructor(verbose) { + super(sinon, verbose); + } } -module.exports = StubLogger; \ No newline at end of file +module.exports = StubLogger;