update dependencies and devDependencies, update eslint config, address lint issues
authorJustin Wind <justin.wind+git@gmail.com>
Sat, 16 Mar 2024 20:07:30 +0000 (13:07 -0700)
committerJustin Wind <justin.wind+git@gmail.com>
Sat, 16 Mar 2024 20:09:28 +0000 (13:09 -0700)
12 files changed:
.eslintrc.json [deleted file]
.npmrc [new file with mode: 0644]
eslint.config.js [new file with mode: 0644]
package-lock.json
package.json
src/common.js
src/db/postgres/index.js
src/db/sqlite/index.js
src/manager.js
src/service.js
src/template/authorization-request-html.js
test/src/service.js

diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644 (file)
index a5481e7..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-{
-  "env": {
-    "browser": false,
-    "es6": true,
-    "node": true
-  },
-  "extends": [
-    "eslint:recommended",
-    "plugin:node/recommended",
-    "plugin:security/recommended-legacy",
-    "plugin:sonarjs/recommended"
-  ],
-  "parserOptions": {
-    "ecmaVersion": "latest"
-  },
-  "plugins": [
-    "node",
-    "security",
-    "sonarjs"
-  ],
-  "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"
-    ],
-    "strict": "error",
-    "vars-on-top": "error"
-  }
-}
diff --git a/.npmrc b/.npmrc
new file mode 100644 (file)
index 0000000..258cd85
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+message="bump package version to %s"
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644 (file)
index 0000000..e02ca72
--- /dev/null
@@ -0,0 +1,111 @@
+'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();
+
+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",
+    },
+  },
+];
index 52d79ad4e9c125345e18d68240dbd24ade898da8..620e8cbcf9debdf69cf256030944cc3fb3e5c606 100644 (file)
       "license": "ISC",
       "dependencies": {
         "@squeep/amqp-helper": "git+https://git.squeep.com/squeep-amqp-helper#v1.0.0",
-        "@squeep/api-dingus": "^2.0.1",
+        "@squeep/api-dingus": "^2.1.0",
         "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.3.2",
         "@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.4.0",
+        "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.5.3",
         "@squeep/indieauth-helper": "^1.4.1",
         "@squeep/logger-json-console": "^3.0.1",
-        "@squeep/mystery-box": "^2.0.1",
+        "@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.0",
+        "@squeep/roman": "^1.0.1",
         "@squeep/web-linking": "^1.0.8",
-        "better-sqlite3": "^9.2.2",
+        "better-sqlite3": "^9.4.3",
         "pg-promise": "^11.5.4",
         "uuid": "^9.0.1"
       },
       "devDependencies": {
         "@squeep/test-helper": "git+https://git.squeep.com/squeep-test-helper#v1.0.1",
-        "eslint": "^8.56.0",
-        "eslint-plugin-node": "^11.1.0",
+        "eslint": "^8.57.0",
+        "eslint-plugin-n": "^16.6.2",
         "eslint-plugin-promise": "^6.1.1",
-        "eslint-plugin-security": "^2.1.0",
-        "eslint-plugin-sonarjs": "^0.23.0",
+        "eslint-plugin-security": "^2.1.1",
+        "eslint-plugin-sonarjs": "^0.24.0",
         "html-minifier-lint": "^2.0.0",
-        "mocha": "^10.2.0",
+        "mocha": "^10.3.0",
         "mocha-steps": "^1.3.0",
         "nyc": "^15.1.0",
         "pre-commit": "^1.2.2",
       }
     },
     "node_modules/@eslint/js": {
-      "version": "8.56.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
-      "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
+      "version": "8.57.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+      "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
       }
     },
     "node_modules/@humanwhocodes/config-array": {
-      "version": "0.11.13",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
-      "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
+      "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.1",
-        "debug": "^4.1.1",
+        "@humanwhocodes/object-schema": "^2.0.2",
+        "debug": "^4.3.1",
         "minimatch": "^3.0.5"
       },
       "engines": {
       }
     },
     "node_modules/@humanwhocodes/object-schema": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
-      "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
+      "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
       "dev": true
     },
     "node_modules/@istanbuljs/load-nyc-config": {
       }
     },
     "node_modules/@squeep/api-dingus": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@squeep/api-dingus/-/api-dingus-2.0.1.tgz",
-      "integrity": "sha512-b4FWPyHNpn8JtvrTQszukz6mF5OmqhJba0czVffCzhOdbfUk6PKejDRjAtSj4m8fgn4QnvvtAOTHBDvQwNAftw==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@squeep/api-dingus/-/api-dingus-2.1.0.tgz",
+      "integrity": "sha512-SCLPHbSHTz5en5XO8IMyTLr6R+0jIDpL3dSxS3e4XLC3521LzorNywGteMdnZKhwXwahjf4XngxNzmO0kFp6Kw==",
       "dependencies": {
         "@squeep/log-helper": "^1.0.0",
         "mime-db": "^1.52.0",
       }
     },
     "node_modules/@squeep/mystery-box": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@squeep/mystery-box/-/mystery-box-2.0.1.tgz",
-      "integrity": "sha512-is8Uqvcm27pm49ZaQL/KOizo89SiTuTZElQoyuPX34TvcnsOTN2eN2YxdVSwKusZwYi+mmE8brrAtBcM/Ttpwg==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@squeep/mystery-box/-/mystery-box-2.0.2.tgz",
+      "integrity": "sha512-YoVx9F/ZFOdgPrt5ey3Vg+ttK4nsnfeSjzVDBOCB1L5q2H1V2wZ4DV0/l7mkqPgHHojGeJqncGs/KhB6Lu916g==",
       "engines": {
         "node": "^14 >=14.18.0 || >=15.7.0"
       }
       }
     },
     "node_modules/@squeep/roman": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/@squeep/roman/-/roman-1.0.0.tgz",
-      "integrity": "sha512-D02jDw/we8tc6QiCPor7tWVviY8MLITyp/egqp3XqrrKtsFMYdguAhaFKUmIBu1ZL1uPKgoLBOy8hIptmh8cWA=="
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@squeep/roman/-/roman-1.0.1.tgz",
+      "integrity": "sha512-mGh8duO0LQusXzGf4N4Um1T9CxKZBHe1i9QvvUCq8f3U2qipugufAUxolMLq3N56wvcD13RcI9R6swIxxIAS8Q=="
     },
     "node_modules/@squeep/test-helper": {
       "version": "1.0.1",
         "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"
+      }
+    },
     "node_modules/@squeep/web-linking": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/@squeep/web-linking/-/web-linking-1.0.8.tgz",
       }
     },
     "node_modules/aproba": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+      "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
       "optional": true
     },
     "node_modules/archy": {
       ]
     },
     "node_modules/better-sqlite3": {
-      "version": "9.2.2",
-      "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.2.2.tgz",
-      "integrity": "sha512-qwjWB46il0lsDkeB4rSRI96HyDQr8sxeu1MkBVLMrwusq1KRu4Bpt1TMI+8zIJkDUtZ3umjAkaEjIlokZKWCQw==",
+      "version": "9.4.3",
+      "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.4.3.tgz",
+      "integrity": "sha512-ud0bTmD9O3uWJGuXDltyj3R47Nz0OHX8iqPOT5PMspGqlu/qQFn+5S2eFBUCrySpavTjFXbi4EgrfVvPAHlImw==",
       "hasInstallScript": true,
       "dependencies": {
         "bindings": "^1.5.0",
         "node": ">=4"
       }
     },
+    "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",
       }
     },
     "node_modules/eslint": {
-      "version": "8.56.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
-      "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
+      "version": "8.57.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+      "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.2.0",
         "@eslint-community/regexpp": "^4.6.1",
         "@eslint/eslintrc": "^2.1.4",
-        "@eslint/js": "8.56.0",
-        "@humanwhocodes/config-array": "^0.11.13",
+        "@eslint/js": "8.57.0",
+        "@humanwhocodes/config-array": "^0.11.14",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
         "@ungap/structured-clone": "^1.2.0",
         "url": "https://opencollective.com/eslint"
       }
     },
+    "node_modules/eslint-compat-utils": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz",
+      "integrity": "sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "peerDependencies": {
+        "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",
         "eslint": ">=4.19.1"
       }
     },
+    "node_modules/eslint-plugin-es-x": {
+      "version": "7.5.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.5.0.tgz",
+      "integrity": "sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==",
+      "dev": true,
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.1.2",
+        "@eslint-community/regexpp": "^4.6.0",
+        "eslint-compat-utils": "^0.1.2"
+      },
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ota-meshi"
+      },
+      "peerDependencies": {
+        "eslint": ">=8"
+      }
+    },
+    "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==",
+      "dev": true,
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.4.0",
+        "builtins": "^5.0.1",
+        "eslint-plugin-es-x": "^7.5.0",
+        "get-tsconfig": "^4.7.0",
+        "globals": "^13.24.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",
+        "semver": "^7.5.3"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mysticatea"
+      },
+      "peerDependencies": {
+        "eslint": ">=7.0.0"
+      }
+    },
     "node_modules/eslint-plugin-node": {
       "version": "11.1.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
       }
     },
     "node_modules/eslint-plugin-security": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-2.1.0.tgz",
-      "integrity": "sha512-ywxclP954bf8d3gr6KOQ/AFc+PRvWuhOxtPOEtiHmVYiZr/mcgQtmSJq6+hTEXC5ylTjHnPPG+PEnzlDiWMXbQ==",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-2.1.1.tgz",
+      "integrity": "sha512-7cspIGj7WTfR3EhaILzAPcfCo5R9FbeWvbgsPYWivSurTBKW88VQxtP3c4aWMG9Hz/GfJlJVdXEJ3c8LqS+u2w==",
       "dev": true,
       "dependencies": {
         "safe-regex": "^2.1.1"
       }
     },
     "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==",
+      "version": "0.24.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.24.0.tgz",
+      "integrity": "sha512-87zp50mbbNrSTuoEOebdRQBPa0mdejA5UEjyuScyIw8hEpEjfWP89Qhkq5xVZfVyVSRQKZc9alVm7yRKQvvUmg==",
       "dev": true,
       "engines": {
-        "node": ">=14"
+        "node": ">=16"
       },
       "peerDependencies": {
         "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
         "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==",
+      "dev": true,
+      "dependencies": {
+        "resolve-pkg-maps": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+      }
+    },
     "node_modules/github-from-package": {
       "version": "0.0.0",
       "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
         "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-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
     },
     "node_modules/mocha": {
-      "version": "10.2.0",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
-      "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz",
+      "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==",
       "dev": true,
       "dependencies": {
         "ansi-colors": "4.1.1",
         "diff": "5.0.0",
         "escape-string-regexp": "4.0.0",
         "find-up": "5.0.0",
-        "glob": "7.2.0",
+        "glob": "8.1.0",
         "he": "1.2.0",
         "js-yaml": "4.1.0",
         "log-symbols": "4.1.0",
         "minimatch": "5.0.1",
         "ms": "2.1.3",
-        "nanoid": "3.3.3",
         "serialize-javascript": "6.0.0",
         "strip-json-comments": "3.1.1",
         "supports-color": "8.1.1",
       },
       "engines": {
         "node": ">= 14.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/mochajs"
       }
     },
     "node_modules/mocha-steps": {
         "balanced-match": "^1.0.0"
       }
     },
+    "node_modules/mocha/node_modules/glob": {
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+      "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+      "dev": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^5.0.1",
+        "once": "^1.3.0"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
     "node_modules/mocha/node_modules/minimatch": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
     },
-    "node_modules/nanoid": {
-      "version": "3.3.3",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
-      "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
-      "dev": true,
-      "bin": {
-        "nanoid": "bin/nanoid.cjs"
-      },
-      "engines": {
-        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
-      }
-    },
     "node_modules/napi-build-utils": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
       }
     },
     "node_modules/node-addon-api": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz",
-      "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==",
-      "optional": true
+      "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==",
+      "optional": true,
+      "engines": {
+        "node": "^16 || ^18 || >= 20"
+      }
     },
     "node_modules/node-fetch": {
       "version": "2.7.0",
         "node": ">=0.10.0"
       }
     },
+    "node_modules/node-linux-pam/node_modules/aproba": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+      "optional": true
+    },
     "node_modules/node-linux-pam/node_modules/are-we-there-yet": {
       "version": "1.1.7",
       "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
         "node": ">=4"
       }
     },
+    "node_modules/resolve-pkg-maps": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+      "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+      }
+    },
     "node_modules/responselike": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
       }
     },
     "@eslint/js": {
-      "version": "8.56.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
-      "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
+      "version": "8.57.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+      "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
       "dev": true
     },
     "@humanwhocodes/config-array": {
-      "version": "0.11.13",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
-      "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
+      "version": "0.11.14",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+      "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
       "dev": true,
       "requires": {
-        "@humanwhocodes/object-schema": "^2.0.1",
-        "debug": "^4.1.1",
+        "@humanwhocodes/object-schema": "^2.0.2",
+        "debug": "^4.3.1",
         "minimatch": "^3.0.5"
       }
     },
       "dev": true
     },
     "@humanwhocodes/object-schema": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
-      "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
+      "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==",
       "dev": true
     },
     "@istanbuljs/load-nyc-config": {
       }
     },
     "@squeep/api-dingus": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@squeep/api-dingus/-/api-dingus-2.0.1.tgz",
-      "integrity": "sha512-b4FWPyHNpn8JtvrTQszukz6mF5OmqhJba0czVffCzhOdbfUk6PKejDRjAtSj4m8fgn4QnvvtAOTHBDvQwNAftw==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@squeep/api-dingus/-/api-dingus-2.1.0.tgz",
+      "integrity": "sha512-SCLPHbSHTz5en5XO8IMyTLr6R+0jIDpL3dSxS3e4XLC3521LzorNywGteMdnZKhwXwahjf4XngxNzmO0kFp6Kw==",
       "requires": {
         "@squeep/log-helper": "^1.0.0",
         "mime-db": "^1.52.0",
     },
     "@squeep/html-template-helper": {
       "version": "git+https://git.squeep.com/squeep-html-template-helper#100046316a87631fb8814f80b35647709e6c7319",
-      "from": "@squeep/html-template-helper@git+https://git.squeep.com/squeep-html-template-helper#v1.4.0",
+      "from": "@squeep/html-template-helper@git+https://git.squeep.com/squeep-html-template-helper#v1.5.3",
       "requires": {
         "@squeep/lazy-property": "^1.1.2"
       }
       "integrity": "sha512-Po4PPtKHoYHuDyx/PMdHdIByCeArVh2McGCw8IxTaFBf+PCdAosZmDNpreKb2Xw7OVpbkX1u3iOmrVgQWv6aBg=="
     },
     "@squeep/mystery-box": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@squeep/mystery-box/-/mystery-box-2.0.1.tgz",
-      "integrity": "sha512-is8Uqvcm27pm49ZaQL/KOizo89SiTuTZElQoyuPX34TvcnsOTN2eN2YxdVSwKusZwYi+mmE8brrAtBcM/Ttpwg=="
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@squeep/mystery-box/-/mystery-box-2.0.2.tgz",
+      "integrity": "sha512-YoVx9F/ZFOdgPrt5ey3Vg+ttK4nsnfeSjzVDBOCB1L5q2H1V2wZ4DV0/l7mkqPgHHojGeJqncGs/KhB6Lu916g=="
     },
     "@squeep/resource-authentication-module": {
       "version": "git+https://git.squeep.com/squeep-resource-authentication-module#0dce6b122b90dc9d2fd3b7191cdef4d41e256ae3",
       }
     },
     "@squeep/roman": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/@squeep/roman/-/roman-1.0.0.tgz",
-      "integrity": "sha512-D02jDw/we8tc6QiCPor7tWVviY8MLITyp/egqp3XqrrKtsFMYdguAhaFKUmIBu1ZL1uPKgoLBOy8hIptmh8cWA=="
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@squeep/roman/-/roman-1.0.1.tgz",
+      "integrity": "sha512-mGh8duO0LQusXzGf4N4Um1T9CxKZBHe1i9QvvUCq8f3U2qipugufAUxolMLq3N56wvcD13RcI9R6swIxxIAS8Q=="
     },
     "@squeep/test-helper": {
       "version": "git+https://git.squeep.com/squeep-test-helper#cc0f69b40de9ae3342f1b7a1784d37769e7f1e84",
           "requires": {
             "safe-regex": "^2.1.1"
           }
+        },
+        "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,
+          "requires": {}
         }
       }
     },
       }
     },
     "aproba": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-      "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+      "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
       "optional": true
     },
     "archy": {
       "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
     },
     "better-sqlite3": {
-      "version": "9.2.2",
-      "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.2.2.tgz",
-      "integrity": "sha512-qwjWB46il0lsDkeB4rSRI96HyDQr8sxeu1MkBVLMrwusq1KRu4Bpt1TMI+8zIJkDUtZ3umjAkaEjIlokZKWCQw==",
+      "version": "9.4.3",
+      "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-9.4.3.tgz",
+      "integrity": "sha512-ud0bTmD9O3uWJGuXDltyj3R47Nz0OHX8iqPOT5PMspGqlu/qQFn+5S2eFBUCrySpavTjFXbi4EgrfVvPAHlImw==",
       "requires": {
         "bindings": "^1.5.0",
         "prebuild-install": "^7.1.1"
       "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
       "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
     },
+    "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
+    },
+    "builtins": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+      "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+      "dev": true,
+      "requires": {
+        "semver": "^7.0.0"
+      }
+    },
     "cacheable-lookup": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz",
       "dev": true
     },
     "eslint": {
-      "version": "8.56.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
-      "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
+      "version": "8.57.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+      "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
       "dev": true,
       "requires": {
         "@eslint-community/eslint-utils": "^4.2.0",
         "@eslint-community/regexpp": "^4.6.1",
         "@eslint/eslintrc": "^2.1.4",
-        "@eslint/js": "8.56.0",
-        "@humanwhocodes/config-array": "^0.11.13",
+        "@eslint/js": "8.57.0",
+        "@humanwhocodes/config-array": "^0.11.14",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
         "@ungap/structured-clone": "^1.2.0",
         "text-table": "^0.2.0"
       }
     },
+    "eslint-compat-utils": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.1.2.tgz",
+      "integrity": "sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==",
+      "dev": true,
+      "requires": {}
+    },
     "eslint-plugin-es": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz",
         "regexpp": "^3.0.0"
       }
     },
+    "eslint-plugin-es-x": {
+      "version": "7.5.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.5.0.tgz",
+      "integrity": "sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==",
+      "dev": true,
+      "requires": {
+        "@eslint-community/eslint-utils": "^4.1.2",
+        "@eslint-community/regexpp": "^4.6.0",
+        "eslint-compat-utils": "^0.1.2"
+      }
+    },
+    "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==",
+      "dev": true,
+      "requires": {
+        "@eslint-community/eslint-utils": "^4.4.0",
+        "builtins": "^5.0.1",
+        "eslint-plugin-es-x": "^7.5.0",
+        "get-tsconfig": "^4.7.0",
+        "globals": "^13.24.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",
+        "semver": "^7.5.3"
+      }
+    },
     "eslint-plugin-node": {
       "version": "11.1.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
       "requires": {}
     },
     "eslint-plugin-security": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-2.1.0.tgz",
-      "integrity": "sha512-ywxclP954bf8d3gr6KOQ/AFc+PRvWuhOxtPOEtiHmVYiZr/mcgQtmSJq6+hTEXC5ylTjHnPPG+PEnzlDiWMXbQ==",
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-2.1.1.tgz",
+      "integrity": "sha512-7cspIGj7WTfR3EhaILzAPcfCo5R9FbeWvbgsPYWivSurTBKW88VQxtP3c4aWMG9Hz/GfJlJVdXEJ3c8LqS+u2w==",
       "dev": true,
       "requires": {
         "safe-regex": "^2.1.1"
       }
     },
     "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==",
+      "version": "0.24.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.24.0.tgz",
+      "integrity": "sha512-87zp50mbbNrSTuoEOebdRQBPa0mdejA5UEjyuScyIw8hEpEjfWP89Qhkq5xVZfVyVSRQKZc9alVm7yRKQvvUmg==",
       "dev": true,
       "requires": {}
     },
       "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
       "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="
     },
+    "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==",
+      "dev": true,
+      "requires": {
+        "resolve-pkg-maps": "^1.0.0"
+      }
+    },
     "github-from-package": {
       "version": "0.0.0",
       "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
         "binary-extensions": "^2.0.0"
       }
     },
+    "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,
+      "requires": {
+        "builtin-modules": "^3.3.0"
+      }
+    },
     "is-core-module": {
       "version": "2.13.1",
       "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
       "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
     },
     "mocha": {
-      "version": "10.2.0",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
-      "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.3.0.tgz",
+      "integrity": "sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==",
       "dev": true,
       "requires": {
         "ansi-colors": "4.1.1",
         "diff": "5.0.0",
         "escape-string-regexp": "4.0.0",
         "find-up": "5.0.0",
-        "glob": "7.2.0",
+        "glob": "8.1.0",
         "he": "1.2.0",
         "js-yaml": "4.1.0",
         "log-symbols": "4.1.0",
         "minimatch": "5.0.1",
         "ms": "2.1.3",
-        "nanoid": "3.3.3",
         "serialize-javascript": "6.0.0",
         "strip-json-comments": "3.1.1",
         "supports-color": "8.1.1",
             "balanced-match": "^1.0.0"
           }
         },
+        "glob": {
+          "version": "8.1.0",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+          "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+          "dev": true,
+          "requires": {
+            "fs.realpath": "^1.0.0",
+            "inflight": "^1.0.4",
+            "inherits": "2",
+            "minimatch": "^5.0.1",
+            "once": "^1.3.0"
+          }
+        },
         "minimatch": {
           "version": "5.0.1",
           "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
       "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
     },
-    "nanoid": {
-      "version": "3.3.3",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
-      "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
-      "dev": true
-    },
     "napi-build-utils": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
       }
     },
     "node-addon-api": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz",
-      "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==",
+      "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==",
       "optional": true
     },
     "node-fetch": {
           "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
           "optional": true
         },
+        "aproba": {
+          "version": "1.2.0",
+          "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+          "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+          "optional": true
+        },
         "are-we-there-yet": {
           "version": "1.1.7",
           "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
       "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
       "dev": true
     },
+    "resolve-pkg-maps": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+      "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+      "dev": true
+    },
     "responselike": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
index 1f2712084f600cb8209ed46ec312bf716f1b2cdc..d2c2de0a9d8814b4f365a82929db3e46af883079 100644 (file)
@@ -14,7 +14,7 @@
   "scripts": {
     "coverage": "nyc npm test",
     "coverage-check": "nyc check-coverage",
-    "eslint": "eslint *.js src",
+    "eslint": "eslint server.js src",
     "test": "mocha --recursive"
   },
   "pre-commit": [
   "license": "ISC",
   "dependencies": {
     "@squeep/amqp-helper": "git+https://git.squeep.com/squeep-amqp-helper#v1.0.0",
-    "@squeep/api-dingus": "^2.0.1",
+    "@squeep/api-dingus": "^2.1.0",
     "@squeep/authentication-module": "git+https://git.squeep.com/squeep-authentication-module/#v1.3.2",
     "@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.4.0",
+    "@squeep/html-template-helper": "git+https://git.squeep.com/squeep-html-template-helper#v1.5.3",
     "@squeep/indieauth-helper": "^1.4.1",
     "@squeep/logger-json-console": "^3.0.1",
-    "@squeep/mystery-box": "^2.0.1",
+    "@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.0",
+    "@squeep/roman": "^1.0.1",
     "@squeep/web-linking": "^1.0.8",
-    "better-sqlite3": "^9.2.2",
+    "better-sqlite3": "^9.4.3",
     "pg-promise": "^11.5.4",
     "uuid": "^9.0.1"
   },
   "devDependencies": {
     "@squeep/test-helper": "git+https://git.squeep.com/squeep-test-helper#v1.0.1",
-    "eslint": "^8.56.0",
-    "eslint-plugin-node": "^11.1.0",
+    "eslint": "^8.57.0",
+    "eslint-plugin-n": "^16.6.2",
     "eslint-plugin-promise": "^6.1.1",
-    "eslint-plugin-security": "^2.1.0",
-    "eslint-plugin-sonarjs": "^0.23.0",
+    "eslint-plugin-security": "^2.1.1",
+    "eslint-plugin-sonarjs": "^0.24.0",
     "html-minifier-lint": "^2.0.0",
-    "mocha": "^10.2.0",
+    "mocha": "^10.3.0",
     "mocha-steps": "^1.3.0",
     "nyc": "^15.1.0",
     "pre-commit": "^1.2.2",
index 7b9f7adc659bb6d01a2c0ece8a7e791b6e7e363b..a9427c2e1f5b392d653c265487fa5bbf2ea64a65 100644 (file)
@@ -2,8 +2,8 @@
 
 const { common } = require('@squeep/api-dingus');
 
-const { randomBytes } = require('crypto');
-const { promisify } = require('util');
+const { randomBytes } = require('node:crypto');
+const { promisify } = require('node:util');
 const randomBytesAsync = promisify(randomBytes);
 
 /**
@@ -58,7 +58,7 @@ const ensureArray = (x) => {
 const freezeDeep = (o) => {
   Object.freeze(o);
   Object.getOwnPropertyNames(o).forEach((prop) => {
-    if (Object.hasOwnProperty.call(o, prop)
+    if (Object.hasOwn(o, prop)
     &&  ['object', 'function'].includes(typeof o[prop]) // eslint-disable-line security/detect-object-injection
     &&  !Object.isFrozen(o[prop])) { // eslint-disable-line security/detect-object-injection
       return freezeDeep(o[prop]); // eslint-disable-line security/detect-object-injection
@@ -134,7 +134,7 @@ const dateToEpoch = (date) => {
 
 
 const omit = (o, props) => {
-  return Object.fromEntries(Object.entries(o).filter(([k]) => !props.includes(k)))
+  return Object.fromEntries(Object.entries(o).filter(([k]) => !props.includes(k)));
 };
 
 
index 535a90153c50170662d1f57f9a1772c01c94c690..184e41b220f570f457764b6ae2b8dd1e215dc53d 100644 (file)
@@ -225,6 +225,11 @@ class DatabasePostgres extends Database {
   }
 
 
+  static _almanacErrorThrow() {
+    throw new DBErrors.UnexpectedResult('did not update almanac');
+  }
+
+
   async almanacGetAll(dbCtx) {
     const _scope = _fileScope('almanacGetAll');
     this.logger.debug(_scope, 'called');
@@ -245,7 +250,7 @@ class DatabasePostgres extends Database {
     try {
       const result = await dbCtx.result(this.statement.almanacUpsert, { event, date: date ?? new Date() });
       if (result.rowCount != 1) {
-        throw new DBErrors.UnexpectedResult('did not upsert almanac event');
+        this.constructor._almanacErrorThrow();
       }
     } catch (e) {
       this.logger.error(_scope, 'failed', { error: e, event, date });
@@ -502,7 +507,7 @@ class DatabasePostgres extends Database {
         // Update the last cleanup time
         const result = await txCtx.result(this.statement.almanacUpsert, { event: almanacEvent, date: now });
         if (result.rowCount != 1) {
-          throw new DBErrors.UnexpectedResult('did not update almanac');
+          this.constructor._almanacErrorThrow();
         }
 
         this.logger.debug(_scope, 'completed', { scopesRemoved, atLeastMsSinceLast });
@@ -581,7 +586,7 @@ class DatabasePostgres extends Database {
         // Update the last cleanup time
         const result = await txCtx.result(this.statement.almanacUpsert, { event: almanacEvent, date: now });
         if (result.rowCount != 1) {
-          throw new DBErrors.UnexpectedResult('did not update almanac');
+          this.constructor._almanacErrorThrow();
         }
 
         this.logger.debug(_scope, 'completed', { tokensRemoved, codeLifespanSeconds, atLeastMsSinceLast });
@@ -681,7 +686,7 @@ class DatabasePostgres extends Database {
       }
       const almanacResult = await dbCtx.result(this.statement.almanacUpsert, { event: almanacEvent, date: new Date() });
       if (almanacResult.rowCount != 1) {
-        throw new DBErrors.UnexpectedResult('did not update almanac');
+        this.constructor._almanacErrorThrow();
       }
     } catch (e) {
       this.logger.error(_scope, 'failed', { error: e, ...redeemedData });
index 453dbf8eada1b9d39d79ac2c47a6e27738c59b40..97027be662733e4cac566a7eccb284bd9256aad0 100644 (file)
@@ -267,6 +267,11 @@ class DatabaseSQLite extends Database {
   }
 
 
+  static _almanacErrorThrow() {
+    throw new DBErrors.UnexpectedResult('did not update almanac');
+  }
+
+
   almanacGetAll(dbCtx) { // eslint-disable-line no-unused-vars
     const _scope = _fileScope('almanacGetAll');
     this.logger.debug(_scope, 'called');
@@ -289,7 +294,7 @@ class DatabaseSQLite extends Database {
       const epoch = common.dateToEpoch(date);
       const result = this.statement.almanacUpsert.run({ event, epoch });
       if (result.changes != 1) {
-        throw new DBErrors.UnexpectedResult('did not upsert almanac event');
+        this.constructor._almanacErrorThrow();
       }
     } catch (e) {
       this.logger.error(_scope, 'failed', { error: e, event, date });
@@ -580,7 +585,7 @@ class DatabaseSQLite extends Database {
         // Update the last cleanup time
         const result = this.statement.almanacUpsert.run({ event: almanacEvent, epoch: nowEpoch });
         if (result.changes != 1) {
-          throw new DBErrors.UnexpectedResult('did not update almanac');
+          this.constructor._almanacErrorThrow();
         }
 
         this.logger.debug(_scope, 'finished', { scopesRemoved, atLeastMsSinceLast });
@@ -658,7 +663,7 @@ class DatabaseSQLite extends Database {
         // Update the last cleanup time
         const result = this.statement.almanacUpsert.run({ event: almanacEvent, epoch: nowEpoch });
         if (result.changes != 1) {
-          throw new DBErrors.UnexpectedResult('did not update almanac');
+          this.constructor._almanacErrorThrow();
         }
 
         this.logger.debug(_scope, 'finished', { tokensRemoved, codeLifespanSeconds, atLeastMsSinceLast });
@@ -786,7 +791,7 @@ class DatabaseSQLite extends Database {
       const epoch = common.dateToEpoch();
       const almanacResult = this.statement.almanacUpsert.run({ event: almanacEvent, epoch });
       if (almanacResult.changes != 1) {
-        throw new DBErrors.UnexpectedResult('did not update almanac');
+        this.constructor._almanacErrorThrow();
       }
 
     } catch (e) {
index c79c7529670b8b83dba45f55ccb824716bd427c6..c7fe0df1b8d73f135e8a1d3f953f64b99df4e1cc 100644 (file)
@@ -196,9 +196,10 @@ class Manager {
 
     Manager._sensitiveResponse(res);
 
-    ctx.session = Object.assign({}, ctx.session, {
+    ctx.session = {
+      ...ctx.session,
       errorDescriptions: [],
-    });
+    };
 
     // Ingest and validate expected data, populating ctx.session.
     await this._clientIdRequired(ctx);
@@ -633,7 +634,9 @@ class Manager {
     Manager._sensitiveResponse(res);
 
     // Ensure session exists, persisting any login session data.
-    ctx.session = Object.assign({}, ctx.session);
+    ctx.session = {
+      ...ctx.session,
+    };
     try {
       // Recover the session established on initial auth request.
       const oldSession = await this.mysteryBox.unpack(ctx.parsedBody['session']);
@@ -789,9 +792,10 @@ class Manager {
   async _ingestPostAuthorizationRequest(ctx) {
     const _scope = _fileScope('_ingestPostAuthorizationRequest');
 
-    ctx.session = Object.assign({}, ctx.session, {
+    ctx.session = {
+      ...ctx.session,
       errorDescriptions: [],
-    });
+    };
 
     if (!ctx.parsedBody) {
       this.logger.debug(_scope, 'no body data', { ctx });
@@ -1397,7 +1401,9 @@ class Manager {
     const _scope = _fileScope('postToken');
     this.logger.debug(_scope, 'called', { ctx });
 
-    ctx.session = Object.assign({}, ctx.session);
+    ctx.session = {
+      ...ctx.session,
+    };
 
     await this.db.context(async (dbCtx) => {
 
index c1e600691642130c40557cffec8721e43f7a2cef..b26da2f0fa5fa1f6a9f881357ca076196218a5ab 100644 (file)
@@ -13,6 +13,7 @@ const { Authenticator, SessionManager } = require('@squeep/authentication-module
 const { ResourceAuthenticator } = require('@squeep/resource-authentication-module');
 const { TemplateHelper: { initContext } } = require('@squeep/html-template-helper');
 const Enum = require('./enum');
+const { ResponseError } = require('./errors');
 
 const _fileScope = common.fileScope(__filename);
 
@@ -55,6 +56,9 @@ class Service extends Dingus {
     // Information page about service
     this.on(['GET'], '/', this.handlerGetRoot.bind(this));
 
+    // Temmporary to see what rando payload someone is sending us unsolicited
+    this.on(['POST'], '/', this.handlerWhaGwan.bind(this));
+
     // Give load-balancers something to check
     this.on(['GET'], route('healthcheck'), this.handlerGetHealthcheck.bind(this));
 
@@ -108,7 +112,7 @@ class Service extends Dingus {
 
     const logObject = this.asyncLocalStorage.getStore();
     // istanbul ignore else
-    if (logObject) { // debugging in vscode seems to kill ALS, work around
+    if (logObject) { // Debugging in vscode seems to kill ALS, work around
       logObject.requestId = ctx.requestId;
       delete ctx.requestId;
     } else {
@@ -473,6 +477,15 @@ class Service extends Dingus {
   }
 
 
+  /**
+   * Temporary to see what an unsolicited payload contains.
+   */
+  async handlerWhaGwan(req, res, ctx) {
+    this.setResponseType(this.responseTypes, req, res, ctx);
+    await this.ingestBody(req, res, ctx);
+    throw new ResponseError(Enum.ErrorResponse.MethodNotAllowed);
+  }
+
   /**
    * @param {http.IncomingMessage} req 
    * @param {http.ServerResponse} res 
index 3e312af683721642a18357b1a6e99084aa98daca..910431d94d4560039de9a831c4aee3238013e8b9 100644 (file)
@@ -19,13 +19,13 @@ function renderClientIdentifierProperties(hApp) {
   const { url, summary, logo, name } = properties;
 
   parts.push('<span class="client-identifier">');
-  if (url && url.length) {
+  if (url?.length) {
     parts.push(`<a href="${url[0]}">`);
   }
-  if (summary && summary.length) {
+  if (summary?.length) {
     imgTitle = ` title="${summary[0]}"`;
   }
-  if (logo && logo.length) {
+  if (logo?.length) {
     let src, alt;
     if (typeof logo[0] === 'string') {
       src = logo[0];
@@ -35,10 +35,10 @@ function renderClientIdentifierProperties(hApp) {
     }
     parts.push(`<img src="${src}" alt="${alt}"${imgTitle}>`);
   }
-  if (name && name.length) {
+  if (name?.length) {
     parts.push(properties['name'][0]);
   }
-  if (url && url.length) {
+  if (url?.length) {
     parts.push('</a>');
   }
   parts.push('</span>');
@@ -52,7 +52,7 @@ function renderClientIdentifierProperties(hApp) {
  * @returns {String}
  */
 function renderClientIdentifier(clientIdentifier) {
-  const hAppEntries = clientIdentifier && clientIdentifier.items || [];
+  const hAppEntries = clientIdentifier?.items || [];
   return hAppEntries.map(renderClientIdentifierProperties).join('');
 }
 
@@ -74,7 +74,7 @@ function renderProfileOption(profile, selected) {
  */
 function renderProfileFieldset(availableProfiles, hintProfile) {
   if (!availableProfiles || availableProfiles.length <= 1) {
-    const profile = availableProfiles && availableProfiles[0] || hintProfile;
+    const profile = availableProfiles?.[0] || hintProfile;
     return `<input type="hidden" name="me" value="${profile}">`;
   }
   return `
@@ -109,7 +109,7 @@ function renderScopeCheckboxLI(scope, checked) {
     scopeDescription = '';
   }
   let profileClass;
-  if (scope.profiles && scope.profiles.length) {
+  if (scope.profiles?.length) {
     profileClass = ['profile-scope'].concat(scope.profiles.map((profile) => th.escapeCSS(profile))).join(' ');
   } else {
     profileClass = '';
@@ -123,7 +123,7 @@ function renderScopeCheckboxLI(scope, checked) {
 
 
 function renderRequestedScopes(requestedScopes) {
-  if (!requestedScopes || !requestedScopes.length) {
+  if (!requestedScopes?.length) {
     return '';
   }
   return `
@@ -264,11 +264,13 @@ function radioButton(name, value, label, checked = false, indent = 0) {
  */
 function mainContent(ctx, options) { // eslint-disable-line no-unused-vars
   const session = ctx.session || {};
-  const hintedProfile = (session.me && session.me.href) || (session.profiles && session.profiles.length && session.profiles[0]) || '';
+  const hintedProfile = session.me?.href || session.profiles?.[0] || '';
   const scopeIndex = session.scopeIndex || {};
 
-  // Add requested scopes to index, if not already present,
-  // and de-associate requested scopes from profiles.
+  /**
+   * Add requested scopes to index, if not already present,
+   * and de-associate requested scopes from profiles.
+   */
   const scopes = session.scope || [];
   scopes.forEach((scopeName) => {
     if ((scopeName in scopeIndex)) {
index 31365794992b578cbb33b687ac9848d831fd1d6a..ab6646f19ae9ecccb817388cb8bbb71a18396e82 100644 (file)
@@ -291,4 +291,10 @@ describe('Service', function () {
     });
   }); // handlerGetAdminMaintenance
 
+  describe('handlerWhaGwan', function () {
+    it('covers', async function () {
+      await assert.rejects(() => service.handlerWhaGwan(req. res, ctx));
+    });
+  }); // handlerWhaGwan
+
 });
\ No newline at end of file