From f0f172fc1e505e2113c5015a175a5b7d1d085795 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 20 Aug 2023 15:34:16 +0800 Subject: [PATCH 001/170] chore: add folders and files --- .env.example | 0 app.js | 21 +- controllers/apis/admin-controller.js | 0 controllers/apis/followship-controller.js | 0 controllers/apis/reply-controller.js | 0 controllers/apis/tweet-controller.js | 0 controllers/apis/user-controller.js | 0 middleware/api-auth.js | 0 middleware/error-handler.js | 0 middleware/multer.js | 0 package-lock.json | 439 +++++++++++++++++++++- package.json | 4 +- routes/index.js | 0 routes/modules/admin.js | 0 services/admin-services.js | 0 services/followship-services.js | 0 services/reply-services.js | 0 services/tweet-services.js | 0 services/user-services.js | 0 swagger.json | 111 ++++++ 20 files changed, 564 insertions(+), 11 deletions(-) create mode 100644 .env.example create mode 100644 controllers/apis/admin-controller.js create mode 100644 controllers/apis/followship-controller.js create mode 100644 controllers/apis/reply-controller.js create mode 100644 controllers/apis/tweet-controller.js create mode 100644 controllers/apis/user-controller.js create mode 100644 middleware/api-auth.js create mode 100644 middleware/error-handler.js create mode 100644 middleware/multer.js create mode 100644 routes/index.js create mode 100644 routes/modules/admin.js create mode 100644 services/admin-services.js create mode 100644 services/followship-services.js create mode 100644 services/reply-services.js create mode 100644 services/tweet-services.js create mode 100644 services/user-services.js create mode 100644 swagger.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app.js b/app.js index 842c6bd679..b2ad0367c7 100644 --- a/app.js +++ b/app.js @@ -1,15 +1,18 @@ -const express = require('express') -const helpers = require('./_helpers'); +const express = require("express"); +const helpers = require("./_helpers"); -const app = express() -const port = 3000 +const app = express(); +const port = 3000; +const swaggerUi = require("swagger-ui-express"); +const swaggerDocument = require("./swagger.json"); +app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument)); // use helpers.getUser(req) to replace req.user -function authenticated(req, res, next){ +function authenticated(req, res, next) { // passport.authenticate('jwt', { ses... -}; +} -app.get('/', (req, res) => res.send('Hello World!')) -app.listen(port, () => console.log(`Example app listening on port ${port}!`)) +app.get("/", (req, res) => res.send("Hello World!")); +app.listen(port, () => console.log(`Example app listening on port ${port}!`)); -module.exports = app +module.exports = app; diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/controllers/apis/reply-controller.js b/controllers/apis/reply-controller.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/middleware/api-auth.js b/middleware/api-auth.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/middleware/error-handler.js b/middleware/error-handler.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/middleware/multer.js b/middleware/multer.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/package-lock.json b/package-lock.json index aa65e2e434..43a1f7d503 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,9 +29,79 @@ "devDependencies": { "proxyquire": "^2.1.3", "sequelize-test-helpers": "^1.4.2", - "supertest": "^3.3.0" + "supertest": "^3.3.0", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.0" } }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "dev": true, + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@apidevtools/json-schema-ref-parser/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "dev": true + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "dev": true, + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true + }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -71,6 +141,12 @@ "@types/ms": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -230,6 +306,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -537,6 +619,18 @@ "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/dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", @@ -723,6 +817,15 @@ "node": ">=4" } }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -1547,6 +1650,18 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true + }, "node_modules/log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -1972,6 +2087,13 @@ "wrappy": "1" } }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "dev": true, + "peer": true + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -2752,6 +2874,88 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", + "dev": true, + "dependencies": { + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "bin": { + "swagger-jsdoc": "bin/swagger-jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/swagger-jsdoc/node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/swagger-jsdoc/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "dev": true, + "dependencies": { + "@apidevtools/swagger-parser": "10.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.4.2.tgz", + "integrity": "sha512-vT5QxP/NOr9m4gLZl+SpavWI3M9Fdh30+Sdw9rEtZbkqNmNNEPhjXas2xTD9rsJYYdLzAiMfwXvtooWH3xbLJA==", + "dev": true + }, + "node_modules/swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dev": true, + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, "node_modules/timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", @@ -2996,6 +3200,15 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, + "node_modules/yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "13.3.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", @@ -3066,9 +3279,100 @@ "engines": { "node": ">=6" } + }, + "node_modules/z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "dev": true, + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^9.4.1" + } + }, + "node_modules/z-schema/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "optional": true, + "engines": { + "node": "^12.20.0 || >=14" + } } }, "dependencies": { + "@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "dev": true, + "requires": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "dev": true + }, + "@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "dev": true + }, + "@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "dev": true, + "requires": { + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" + } + }, + "@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true + }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -3108,6 +3412,12 @@ "@types/ms": "*" } }, + "@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, "@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -3241,6 +3551,12 @@ "get-intrinsic": "^1.0.2" } }, + "call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -3485,6 +3801,15 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", @@ -3637,6 +3962,12 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -4244,6 +4575,18 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, + "lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -4595,6 +4938,13 @@ "wrappy": "1" } }, + "openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "dev": true, + "peer": true + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -5166,6 +5516,66 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, + "swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", + "dev": true, + "requires": { + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "dependencies": { + "commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "dev": true, + "requires": { + "@apidevtools/swagger-parser": "10.0.3" + } + }, + "swagger-ui-dist": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.4.2.tgz", + "integrity": "sha512-vT5QxP/NOr9m4gLZl+SpavWI3M9Fdh30+Sdw9rEtZbkqNmNNEPhjXas2xTD9rsJYYdLzAiMfwXvtooWH3xbLJA==", + "dev": true + }, + "swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dev": true, + "requires": { + "swagger-ui-dist": ">=5.0.0" + } + }, "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", @@ -5358,6 +5768,12 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, + "yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "dev": true + }, "yargs": { "version": "13.3.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", @@ -5418,6 +5834,27 @@ "lodash": "^4.17.15", "yargs": "^13.3.0" } + }, + "z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "dev": true, + "requires": { + "commander": "^9.4.1", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "dependencies": { + "commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "optional": true + } + } } } } diff --git a/package.json b/package.json index f6a07e1a29..f03080cb39 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,8 @@ "devDependencies": { "proxyquire": "^2.1.3", "sequelize-test-helpers": "^1.4.2", - "supertest": "^3.3.0" + "supertest": "^3.3.0", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.0" } } diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/routes/modules/admin.js b/routes/modules/admin.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/services/admin-services.js b/services/admin-services.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/services/followship-services.js b/services/followship-services.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/services/reply-services.js b/services/reply-services.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/services/tweet-services.js b/services/tweet-services.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/services/user-services.js b/services/user-services.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/swagger.json b/swagger.json new file mode 100644 index 0000000000..5b45cb6776 --- /dev/null +++ b/swagger.json @@ -0,0 +1,111 @@ +{ + "openapi": "3.0.2", + "info": { + "title": "Twitter API", + "version": "1.0" + }, + "tags": [ + { + "name": "Admin", + "description": "API for admins" + }, + { + "name": "User", + "description": "API for users" + } + ], + "servers": [{ "url": "https://api.server.test/v1" }], + + "paths": { + "/api/admin/users": { + "get": { + "tags": ["Admin"], + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/admin/login": { + "post": { + "tags": ["Admin"], + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/admin/tweets": { + "get": { + "tags": ["Admin"], + "description": "", + "parameters": [], + "responses": + } + }, + "/api/admin/tweets/{id}": { + "delete": { + "tags": ["Admin"], + "description": "", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "tweetId", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "succes" + }, + "message": { + "type": "string", + "example": "Successfully delete tweet." + } + } + } + } + } + }, + "401": { + "description": "error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "example": "error" + }, + "message": { + "type": "string", + "example": "Permission is denied." + } + } + } + } + } + } + } + } + } + } +} From 23210be68432e8204465f202f773dee255fadce7 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 20 Aug 2023 15:48:06 +0800 Subject: [PATCH 002/170] add hi --- app.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/app.js b/app.js index 842c6bd679..4efe5877a8 100644 --- a/app.js +++ b/app.js @@ -1,15 +1,15 @@ -const express = require('express') -const helpers = require('./_helpers'); - -const app = express() -const port = 3000 +const express = require("express"); +const helpers = require("./_helpers"); +const app = express(); +const port = 3000; +const hi = "hi"; // use helpers.getUser(req) to replace req.user -function authenticated(req, res, next){ +function authenticated(req, res, next) { // passport.authenticate('jwt', { ses... -}; +} -app.get('/', (req, res) => res.send('Hello World!')) -app.listen(port, () => console.log(`Example app listening on port ${port}!`)) +app.get("/", (req, res) => res.send("Hello World!")); +app.listen(port, () => console.log(`Example app listening on port ${port}!`)); -module.exports = app +module.exports = app; From 9ae4b061a434869d7a8b2413a691c34111789b75 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sun, 20 Aug 2023 21:44:16 +0800 Subject: [PATCH 003/170] feat: add user, tweet, reply, like, followship models --- .eslintignore | 2 + .eslintrc.yml | 12 + app.js | 19 +- .../20190115071418-create-followship.js | 30 - migrations/20190115071419-create-like.js | 30 - migrations/20190115071420-create-reply.js | 33 - ...-user.js => 20230820130753-create-user.js} | 30 +- ...weet.js => 20230820131455-create-tweet.js} | 26 +- migrations/20230820132049-create-reply.js | 37 + migrations/20230820132304-create-like.js | 34 + .../20230820132742-create-followship.js | 40 + models/followship.js | 30 +- models/index.js | 40 +- models/like.js | 30 +- models/reply.js | 31 +- models/tweet.js | 30 +- models/user.js | 36 +- package-lock.json | 8445 ++++++++++++----- package.json | 20 +- 19 files changed, 6521 insertions(+), 2434 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.yml delete mode 100644 migrations/20190115071418-create-followship.js delete mode 100644 migrations/20190115071419-create-like.js delete mode 100644 migrations/20190115071420-create-reply.js rename migrations/{20190115071421-create-user.js => 20230820130753-create-user.js} (63%) rename migrations/{20190115071420-create-tweet.js => 20230820131455-create-tweet.js} (50%) create mode 100644 migrations/20230820132049-create-reply.js create mode 100644 migrations/20230820132304-create-like.js create mode 100644 migrations/20230820132742-create-followship.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..ceaa7dc6e6 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +/node_modules/* +/tests/* \ No newline at end of file diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000000..495c19c369 --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,12 @@ +env: + browser: true + commonjs: true + es2021: true +extends: + - standard +parserOptions: + ecmaVersion: 12 +rules: + arrow-parens: + - warn + - as-needed diff --git a/app.js b/app.js index b2ad0367c7..b27cc6744a 100644 --- a/app.js +++ b/app.js @@ -1,18 +1,15 @@ -const express = require("express"); -const helpers = require("./_helpers"); +const express = require('express') +const helpers = require('./_helpers') -const app = express(); -const port = 3000; -const swaggerUi = require("swagger-ui-express"); -const swaggerDocument = require("./swagger.json"); -app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument)); +const app = express() +const port = 3000 // use helpers.getUser(req) to replace req.user -function authenticated(req, res, next) { +function authenticated (req, res, next) { // passport.authenticate('jwt', { ses... } -app.get("/", (req, res) => res.send("Hello World!")); -app.listen(port, () => console.log(`Example app listening on port ${port}!`)); +app.get('/', (req, res) => res.send('Hello World!')) +app.listen(port, () => console.log(`Example app listening on port ${port}!`)) -module.exports = app; +module.exports = app diff --git a/migrations/20190115071418-create-followship.js b/migrations/20190115071418-create-followship.js deleted file mode 100644 index 4e04770a7c..0000000000 --- a/migrations/20190115071418-create-followship.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; -module.exports = { - up: (queryInterface, Sequelize) => { - return queryInterface.createTable('Followships', { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER - }, - followerId: { - type: Sequelize.INTEGER - }, - followingId: { - type: Sequelize.INTEGER - }, - createdAt: { - allowNull: false, - type: Sequelize.DATE - }, - updatedAt: { - allowNull: false, - type: Sequelize.DATE - } - }); - }, - down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Followships'); - } -}; \ No newline at end of file diff --git a/migrations/20190115071419-create-like.js b/migrations/20190115071419-create-like.js deleted file mode 100644 index 08c9e524d5..0000000000 --- a/migrations/20190115071419-create-like.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; -module.exports = { - up: (queryInterface, Sequelize) => { - return queryInterface.createTable('Likes', { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER - }, - UserId: { - type: Sequelize.INTEGER - }, - TweetId: { - type: Sequelize.INTEGER - }, - createdAt: { - allowNull: false, - type: Sequelize.DATE - }, - updatedAt: { - allowNull: false, - type: Sequelize.DATE - } - }); - }, - down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Likes'); - } -}; \ No newline at end of file diff --git a/migrations/20190115071420-create-reply.js b/migrations/20190115071420-create-reply.js deleted file mode 100644 index ccfd119c53..0000000000 --- a/migrations/20190115071420-create-reply.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; -module.exports = { - up: (queryInterface, Sequelize) => { - return queryInterface.createTable('Replies', { - id: { - allowNull: false, - autoIncrement: true, - primaryKey: true, - type: Sequelize.INTEGER - }, - UserId: { - type: Sequelize.INTEGER - }, - TweetId: { - type: Sequelize.INTEGER - }, - comment: { - type: Sequelize.TEXT - }, - createdAt: { - allowNull: false, - type: Sequelize.DATE - }, - updatedAt: { - allowNull: false, - type: Sequelize.DATE - } - }); - }, - down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Replies'); - } -}; \ No newline at end of file diff --git a/migrations/20190115071421-create-user.js b/migrations/20230820130753-create-user.js similarity index 63% rename from migrations/20190115071421-create-user.js rename to migrations/20230820130753-create-user.js index 2376dbb50d..a48edd4796 100644 --- a/migrations/20190115071421-create-user.js +++ b/migrations/20230820130753-create-user.js @@ -1,42 +1,48 @@ -'use strict'; +'use strict' module.exports = { - up: (queryInterface, Sequelize) => { - return queryInterface.createTable('Users', { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Users', { id: { allowNull: false, autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER }, + name: { + type: Sequelize.STRING + }, email: { type: Sequelize.STRING }, password: { type: Sequelize.STRING }, - name: { + account: { type: Sequelize.STRING }, + introduction: { + type: Sequelize.TEXT + }, avatar: { type: Sequelize.STRING }, - introduction: { - type: Sequelize.TEXT + cover: { + type: Sequelize.STRING }, role: { type: Sequelize.STRING }, - createdAt: { + created_at: { allowNull: false, type: Sequelize.DATE }, - updatedAt: { + updated_at: { allowNull: false, type: Sequelize.DATE } - }); + }) }, - down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Users'); + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Users') } -}; \ No newline at end of file +} diff --git a/migrations/20190115071420-create-tweet.js b/migrations/20230820131455-create-tweet.js similarity index 50% rename from migrations/20190115071420-create-tweet.js rename to migrations/20230820131455-create-tweet.js index 201c8e8245..39df6eb3c1 100644 --- a/migrations/20190115071420-create-tweet.js +++ b/migrations/20230820131455-create-tweet.js @@ -1,30 +1,32 @@ -'use strict'; +'use strict' module.exports = { - up: (queryInterface, Sequelize) => { - return queryInterface.createTable('Tweets', { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Tweets', { id: { allowNull: false, autoIncrement: true, primaryKey: true, type: Sequelize.INTEGER }, - UserId: { - type: Sequelize.INTEGER - }, description: { type: Sequelize.TEXT }, - createdAt: { + user_id: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 1 + }, + created_at: { allowNull: false, type: Sequelize.DATE }, - updatedAt: { + updated_at: { allowNull: false, type: Sequelize.DATE } - }); + }) }, - down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Tweets'); + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Tweets') } -}; \ No newline at end of file +} diff --git a/migrations/20230820132049-create-reply.js b/migrations/20230820132049-create-reply.js new file mode 100644 index 0000000000..75ca7305e5 --- /dev/null +++ b/migrations/20230820132049-create-reply.js @@ -0,0 +1,37 @@ +'use strict' +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Replies', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + comment: { + type: Sequelize.TEXT + }, + user_id: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 1 + }, + tweet_id: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 1 + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }) + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Replies') + } +} diff --git a/migrations/20230820132304-create-like.js b/migrations/20230820132304-create-like.js new file mode 100644 index 0000000000..c1f6d5c21d --- /dev/null +++ b/migrations/20230820132304-create-like.js @@ -0,0 +1,34 @@ +'use strict' +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Likes', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + user_id: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 1 + }, + tweet_id: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 1 + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }) + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Likes') + } +} diff --git a/migrations/20230820132742-create-followship.js b/migrations/20230820132742-create-followship.js new file mode 100644 index 0000000000..8d72d63728 --- /dev/null +++ b/migrations/20230820132742-create-followship.js @@ -0,0 +1,40 @@ +'use strict' +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Followships', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + follower_id: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'Users', + key: 'id' + } + }, + following_id: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'Users', + key: 'id' + } + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }) + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Followships') + } +} diff --git a/models/followship.js b/models/followship.js index 790f3faa39..1ab09e1b89 100644 --- a/models/followship.js +++ b/models/followship.js @@ -1,8 +1,26 @@ -'use strict'; +'use strict' +const { + Model +} = require('sequelize') module.exports = (sequelize, DataTypes) => { - const Followship = sequelize.define('Followship', { - }, {}); - Followship.associate = function(models) { + class Followship extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate (models) { + // define association here + } }; - return Followship; -}; \ No newline at end of file + Followship.init({ + followerId: DataTypes.INTEGER, + followingId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'Followship', + tableName: 'Followships', + underscored: true + }) + return Followship +} diff --git a/models/index.js b/models/index.js index 33f09e7764..e92dffac8b 100644 --- a/models/index.js +++ b/models/index.js @@ -1,37 +1,37 @@ -'use strict'; +'use strict' -const fs = require('fs'); -const path = require('path'); -const Sequelize = require('sequelize'); -const basename = path.basename(__filename); -const env = process.env.NODE_ENV || 'development'; -const config = require(__dirname + '/../config/config.json')[env]; -const db = {}; +const fs = require('fs') +const path = require('path') +const Sequelize = require('sequelize') +const basename = path.basename(__filename) +const env = process.env.NODE_ENV || 'development' +const config = require(__dirname + '/../config/config.json')[env] +const db = {} -let sequelize; +let sequelize if (config.use_env_variable) { - sequelize = new Sequelize(process.env[config.use_env_variable], config); + sequelize = new Sequelize(process.env[config.use_env_variable], config) } else { - sequelize = new Sequelize(config.database, config.username, config.password, config); + sequelize = new Sequelize(config.database, config.username, config.password, config) } fs .readdirSync(__dirname) .filter(file => { - return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); + return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js') }) .forEach(file => { - const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); - db[model.name] = model; - }); + const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes) + db[model.name] = model + }) Object.keys(db).forEach(modelName => { if (db[modelName].associate) { - db[modelName].associate(db); + db[modelName].associate(db) } -}); +}) -db.sequelize = sequelize; -db.Sequelize = Sequelize; +db.sequelize = sequelize +db.Sequelize = Sequelize -module.exports = db; +module.exports = db diff --git a/models/like.js b/models/like.js index c8939de1fc..722a28d70b 100644 --- a/models/like.js +++ b/models/like.js @@ -1,8 +1,26 @@ -'use strict'; +'use strict' +const { + Model +} = require('sequelize') module.exports = (sequelize, DataTypes) => { - const Like = sequelize.define('Like', { - }, {}); - Like.associate = function(models) { + class Like extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate (models) { + // define association here + } }; - return Like; -}; \ No newline at end of file + Like.init({ + userId: DataTypes.INTEGER, + tweetId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'Like', + tableName: 'Likes', + underscored: true + }) + return Like +} diff --git a/models/reply.js b/models/reply.js index 60387f164f..dad239fc0a 100644 --- a/models/reply.js +++ b/models/reply.js @@ -1,8 +1,27 @@ -'use strict'; +'use strict' +const { + Model +} = require('sequelize') module.exports = (sequelize, DataTypes) => { - const Reply = sequelize.define('Reply', { - }, {}); - Reply.associate = function(models) { + class Reply extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate (models) { + // define association here + } }; - return Reply; -}; \ No newline at end of file + Reply.init({ + comment: DataTypes.TEXT, + userId: DataTypes.INTEGER, + tweetId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'Reply', + tableName: 'Replies', + underscored: true + }) + return Reply +} diff --git a/models/tweet.js b/models/tweet.js index a8b6600778..8a6ac8ba13 100644 --- a/models/tweet.js +++ b/models/tweet.js @@ -1,8 +1,26 @@ -'use strict'; +'use strict' +const { + Model +} = require('sequelize') module.exports = (sequelize, DataTypes) => { - const Tweet = sequelize.define('Tweet', { - }, {}); - Tweet.associate = function(models) { + class Tweet extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate (models) { + // define association here + } }; - return Tweet; -}; \ No newline at end of file + Tweet.init({ + description: DataTypes.TEXT, + userId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'Tweet', + tableName: 'Tweets', + underscored: true + }) + return Tweet +} diff --git a/models/user.js b/models/user.js index 82c5f84c83..5f05801375 100644 --- a/models/user.js +++ b/models/user.js @@ -1,8 +1,32 @@ -'use strict'; +'use strict' +const { + Model +} = require('sequelize') module.exports = (sequelize, DataTypes) => { - const User = sequelize.define('User', { - }, {}); - User.associate = function(models) { + class User extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate (models) { + // define association here + } }; - return User; -}; \ No newline at end of file + User.init({ + name: DataTypes.STRING, + email: DataTypes.STRING, + password: DataTypes.STRING, + account: DataTypes.STRING, + introduction: DataTypes.TEXT, + avatar: DataTypes.STRING, + cover: DataTypes.STRING, + role: DataTypes.STRING + }, { + sequelize, + modelName: 'User', + tableName: 'Users', + underscored: true + }) + return User +} diff --git a/package-lock.json b/package-lock.json index 43a1f7d503..ac576c6e54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,41 +18,102 @@ "faker": "^4.1.0", "method-override": "^3.0.0", "mocha": "^6.0.2", - "mysql2": "^1.6.4", + "mysql2": "^2.3.0", "passport": "^0.4.0", "passport-local": "^1.0.0", - "sequelize": "^6.18.0", - "sequelize-cli": "^5.5.0", + "sequelize": "^6.6.5", + "sequelize-cli": "^6.2.0", "sinon": "^10.0.0", "sinon-chai": "^3.3.0" }, "devDependencies": { + "eslint-config-standard": "^17.1.0", "proxyquire": "^2.1.3", "sequelize-test-helpers": "^1.4.2", - "supertest": "^3.3.0", - "swagger-jsdoc": "^6.2.8", - "swagger-ui-express": "^5.0.0" + "standard": "*", + "supertest": "^3.3.0" } }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", - "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "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_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@apidevtools/json-schema-ref-parser/node_modules/argparse": { + "node_modules/@eslint/eslintrc/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/@apidevtools/json-schema-ref-parser/node_modules/js-yaml": { + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", @@ -64,44 +125,148 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@apidevtools/openapi-schemas": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", - "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=10" + "node": "*" } }, - "node_modules/@apidevtools/swagger-methods": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", - "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/@apidevtools/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", + "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", "dev": true, "dependencies": { - "@apidevtools/json-schema-ref-parser": "^9.0.6", - "@apidevtools/openapi-schemas": "^2.0.4", - "@apidevtools/swagger-methods": "^3.0.2", - "@jsdevtools/ono": "^7.1.3", - "call-me-maybe": "^1.0.1", - "z-schema": "^5.0.1" + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" }, - "peerDependencies": { - "openapi-types": ">=7" + "engines": { + "node": ">=10.10.0" } }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -133,35 +298,17 @@ "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" }, - "node_modules/@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, "node_modules/@types/node": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz", "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==" }, - "node_modules/@types/validator": { - "version": "13.7.2", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.2.tgz", - "integrity": "sha512-KFcchQ3h0OPQgFirBRPZr5F/sVjxZsOrQHedj3zi8AH3Zv/hOLx2OLR4hxR5HcfoU+33n69ZuOfzthKVdMoTiw==" - }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -179,6 +326,43 @@ "node": ">= 0.6" } }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/ansi-colors": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", @@ -206,6 +390,11 @@ "node": ">=4" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -214,11 +403,129 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", + "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -227,12 +534,32 @@ "node": "*" } }, + "node_modules/asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -286,6 +613,30 @@ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, + "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/builtins/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -306,11 +657,14 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "dev": true + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } }, "node_modules/camelcase": { "version": "5.3.1", @@ -526,9 +880,38 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", "dependencies": { "es5-ext": "^0.10.50", @@ -562,10 +945,16 @@ "node": ">=0.12" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dependencies": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -682,31 +1071,59 @@ "node": ">= 0.8" } }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-abstract": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz", - "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", + "object-inspect": "^1.12.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" }, "engines": { "node": ">= 0.4" @@ -716,13 +1133,13 @@ } }, "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -732,6 +1149,50 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-iterator-helpers": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.13.tgz", + "integrity": "sha512-LK3VGwzvaPWobO8xzXXGRUOGw8Dcjyfk62CsY/wfHN75CwsJPbuypOYJxK6g5RyEL8YDjIWcl6jgd8foO6mmrA==", + "dev": true, + "dependencies": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.3", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.0", + "safe-array-concat": "^1.0.0" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -805,1301 +1266,1500 @@ "node": ">=0.8.0" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", + "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "^8.47.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "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", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "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", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/eslint-config-standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "engines": { - "node": ">=0.10.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", + "eslint-plugin-promise": "^6.0.0" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "engines": { - "node": ">= 0.6" + "node_modules/eslint-config-standard-jsx": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", + "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peerDependencies": { + "eslint": "^8.8.0", + "eslint-plugin-react": "^7.28.0" } }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" + "ms": "^2.1.1" } }, - "node_modules/express-session": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", - "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", + "node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, "dependencies": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" + "debug": "^3.2.7" }, "engines": { - "node": ">= 0.8.0" + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/express-session/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" } }, - "node_modules/express/node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "node_modules/eslint-module-utils/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "dev": true, "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" } }, - "node_modules/express/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "node_modules/eslint-plugin-es-x": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.2.0.tgz", + "integrity": "sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==", + "dev": true, + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.6.0" + }, "engines": { - "node": ">= 0.6" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=8" } }, - "node_modules/express/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "node_modules/eslint-plugin-es/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": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" + "eslint-visitor-keys": "^1.1.0" }, "engines": { - "node": ">= 0.6" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/express/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, + "node_modules/eslint-plugin-es/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": ">= 0.8" + "node": ">=4" } }, - "node_modules/express/node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "node_modules/eslint-plugin-import": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", + "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.findlastindex": "^1.2.2", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.8.0", + "has": "^1.0.3", + "is-core-module": "^2.13.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.6", + "object.groupby": "^1.0.0", + "object.values": "^1.1.6", + "semver": "^6.3.1", + "tsconfig-paths": "^3.14.2" + }, "engines": { - "node": ">=0.6" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/express/node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "dependencies": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { - "type": "^2.5.0" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/ext/node_modules/type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/faker": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", - "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" + "node_modules/eslint-plugin-import/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_modules/fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "node_modules/eslint-plugin-n": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.1.tgz", + "integrity": "sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==", "dev": true, + "peer": true, "dependencies": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" + "@eslint-community/eslint-utils": "^4.4.0", + "builtins": "^5.0.1", + "eslint-plugin-es-x": "^7.1.0", + "ignore": "^5.2.4", + "is-core-module": "^2.12.1", + "minimatch": "^3.1.2", + "resolve": "^1.22.2", + "semver": "^7.5.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "node_modules/eslint-plugin-n/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.8" + "node": "*" } }, - "node_modules/finalhandler/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "peer": true, "dependencies": { - "ee-first": "1.1.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "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==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "dev": true, "dependencies": { - "locate-path": "^3.0.0" + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" }, "engines": { - "node": ">=6" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, "dependencies": { - "is-buffer": "~2.0.3" + "esutils": "^2.0.2" }, - "bin": { - "flat": "cli.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.12" + "node": "*" } }, - "node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "engines": { - "node": ">= 0.6" + "node_modules/eslint-plugin-react/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_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "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==", + "dev": true, "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, "dependencies": { - "is-property": "^1.0.2" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "eslint-visitor-keys": "^2.0.0" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" } }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, "engines": { - "node": "*" + "node": ">=10" } }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" + "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://github.com/sponsors/ljharb" + "url": "https://opencollective.com/eslint" } }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "node_modules/eslint/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=4.x" + "node": ">=7.0.0" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1" + "ms": "2.1.2" }, "engines": { - "node": ">= 0.4.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "argparse": "^2.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "*" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "p-limit": "^3.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/eslint/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/inflection": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", - "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==", - "engines": [ - "node >= 0.4.0" - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "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==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">= 0.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">= 0.10" + "node": ">=4" } }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, "dependencies": { - "has-bigints": "^1.0.1" + "estraverse": "^5.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4.0" } }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=4.0" } }, - "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "d": "1", + "es5-ext": "~0.10.14" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/express": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", "dependencies": { - "has-tostringtag": "^1.0.0" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.19.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.7", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "node_modules/express-session": { + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", + "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "node_modules/express/node_modules/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", "dependencies": { - "has-tostringtag": "^1.0.0" + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/express/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" } }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "node_modules/express/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "node_modules/express/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dependencies": { - "call-bind": "^1.0.2" + "ee-first": "1.1.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.8" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, + "node_modules/express/node_modules/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", "engines": { - "node": ">= 0.4" + "node": ">=0.6" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/express/node_modules/raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", "dependencies": { - "has-symbols": "^1.0.2" + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "^2.5.0" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "node_modules/ext/node_modules/type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true }, - "node_modules/js-beautify": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", - "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", + "node_modules/faker": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", + "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, "dependencies": { - "config-chain": "^1.1.13", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "nopt": "^5.0.0" - }, - "bin": { - "css-beautify": "js/bin/css-beautify.js", - "html-beautify": "js/bin/html-beautify.js", - "js-beautify": "js/bin/js-beautify.js" - }, - "engines": { - "node": ">=10" + "reusify": "^1.0.4" } }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "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==", + "dev": true, "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "flat-cache": "^3.0.4" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" - }, - "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "node_modules/fill-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "is-object": "~1.0.1", + "merge-descriptors": "~1.0.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dependencies": { - "chalk": "^2.0.1" + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dependencies": { - "get-func-name": "^2.0.0" + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dependencies": { - "yallist": "^3.0.2" + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "node_modules/flat": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", + "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", "dependencies": { - "es5-ext": "~0.10.2" + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" } }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, "engines": { - "node": ">= 0.6" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" + "is-callable": "^1.1.3" } }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "node_modules/method-override": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", - "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", + "node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dev": true, "dependencies": { - "debug": "3.1.0", - "methods": "~1.1.2", - "parseurl": "~1.3.2", - "vary": "~1.1.2" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.12" } }, - "node_modules/method-override/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" + "node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "dev": true, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "engines": { "node": ">= 0.6" } }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", "engines": { "node": ">= 0.6" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dependencies": { - "mime-db": "1.52.0" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">= 0.6" + "node": ">=6 <7 || >=8" } }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", "dependencies": { - "brace-expansion": "^1.1.7" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" + "is-property": "^1.0.2" } }, - "node_modules/mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "dependencies": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "engines": { - "node": ">= 6.0.0" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/mocha/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "engines": { + "node": "*" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true + "node_modules/get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/moment-timezone": { - "version": "0.5.34", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", - "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", + "node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dependencies": { - "moment": ">= 2.9.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" } }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/mysql2": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.7.0.tgz", - "integrity": "sha512-xTWWQPjP5rcrceZQ7CSTKR/4XIDeH/cRkNH/uzvVGQ7W5c7EJ0dXeJUusk7OKhIoHj7uFKUxDVSCfLIl+jluog==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "dependencies": { - "denque": "^1.4.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.5.0", - "long": "^4.0.0", - "lru-cache": "^5.1.1", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 8.0" + "node": ">=10.13.0" } }, - "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", - "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/named-placeholders": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", - "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dependencies": { - "lru-cache": "^4.1.3" + "define-properties": "^1.1.3" }, "engines": { - "node": ">=6.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/named-placeholders/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/named-placeholders/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "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/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "engines": { - "node": ">= 0.6" + "node": ">=4.x" } }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, - "node_modules/nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dependencies": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/nise/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dependencies": { - "isarray": "0.0.1" + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" } }, - "node_modules/node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" + "get-intrinsic": "^1.1.1" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "has-symbols": "^1.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "bin": { + "he": "bin/he" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "ee-first": "1.1.1" + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" }, "engines": { "node": ">= 0.8" } }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { "node": ">= 0.8" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dependencies": { - "wrappy": "1" + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/openapi-types": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", - "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, - "peer": true + "engines": { + "node": ">= 4" + } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, "dependencies": { - "p-try": "^2.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" @@ -2108,1349 +2768,3114 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflection": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz", + "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==", + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dependencies": { - "p-limit": "^2.0.0" + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "engines": { - "node": ">=6" + "node": ">= 0.10" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/passport": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, "dependencies": { - "passport-strategy": "1.x.x", - "pause": "0.0.1" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/passport-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dependencies": { - "passport-strategy": "1.x.x" + "has-bigints": "^1.0.1" }, - "engines": { - "node": ">= 0.4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "engines": { "node": ">=4" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "engines": { - "node": ">=0.10.0" - } - }, - "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==" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" - }, - "node_modules/pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "engines": { + "node": ">=4" + } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/proxyquire": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dependencies": { - "side-channel": "^1.0.4" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=0.6" + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", - "engines": { - "node": ">= 0.8" + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "which-typed-array": "^1.1.11" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/retry-as-promised": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-5.0.0.tgz", - "integrity": "sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA==" + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" }, - "engines": { - "node": ">= 0.8.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/send/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true }, - "node_modules/send/node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "node_modules/send/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "node_modules/iterator.prototype": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.0.tgz", + "integrity": "sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw==", + "dev": true, "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" + "define-properties": "^1.1.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "has-tostringtag": "^1.0.0", + "reflect.getprototypeof": "^1.0.3" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/send/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "node_modules/js-beautify": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", + "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", "dependencies": { - "ee-first": "1.1.1" + "config-chain": "^1.1.13", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "nopt": "^5.0.0" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, - "node_modules/sequelize": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.19.0.tgz", - "integrity": "sha512-B3oGIdpYBERDjRDm74h7Ky67f6ZLcmBXOA7HscYObiOSo4pD7VBc9mtm44wNV7unc0uk8I1d30nbZBTQCE377A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/sequelize" - } - ], + "node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dependencies": { - "@types/debug": "^4.1.7", - "@types/validator": "^13.7.1", - "debug": "^4.3.3", - "dottie": "^2.0.2", - "inflection": "^1.13.2", - "lodash": "^4.17.21", - "moment": "^2.29.1", - "moment-timezone": "^0.5.34", - "pg-connection-string": "^2.5.0", - "retry-as-promised": "^5.0.0", - "semver": "^7.3.5", - "sequelize-pool": "^7.1.0", - "toposort-class": "^1.0.1", - "uuid": "^8.3.2", - "validator": "^13.7.0", - "wkx": "^0.5.0" - }, - "engines": { - "node": ">=10.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "peerDependenciesMeta": { - "ibm_db": { - "optional": true - }, - "mariadb": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-hstore": { - "optional": true - }, - "snowflake-sdk": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "tedious": { - "optional": true - } + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/sequelize-cli": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-5.5.1.tgz", - "integrity": "sha512-ZM4kUZvY3y14y+Rq3cYxGH7YDJz11jWHcN2p2x7rhAIemouu4CEXr5ebw30lzTBtyXV4j2kTO+nUjZOqzG7k+Q==", + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, "dependencies": { - "bluebird": "^3.5.3", - "cli-color": "^1.4.0", - "fs-extra": "^7.0.1", - "js-beautify": "^1.8.8", - "lodash": "^4.17.5", - "resolve": "^1.5.0", - "umzug": "^2.1.0", - "yargs": "^13.1.0" + "minimist": "^1.2.0" }, "bin": { - "sequelize": "lib/sequelize", - "sequelize-cli": "lib/sequelize" - }, - "engines": { - "node": ">=6.0.0" + "json5": "lib/cli.js" } }, - "node_modules/sequelize-pool": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", - "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=4.0" } }, - "node_modules/sequelize-test-helpers": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.2.tgz", - "integrity": "sha512-v7Yy9DKjzFA/OHLtxvFClgN2CKA9cRwxn9+6ha6xoqUzRngXdsbrmle0KD1onSqnCwVIweWlRTLJxcEl1ueozA==", + "node_modules/jsx-ast-utils/node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">= 8.10.0" + "node": ">= 0.4" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/davesag" - }, - "peerDependencies": { - "chai": ">= 4", - "sinon": ">= 10.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sequelize/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "dependencies": { - "ms": "2.1.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 0.8.0" } }, - "node_modules/sequelize/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==", + "node_modules/load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/sequelize/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "node_modules/load-json-file/node_modules/type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/sequelize/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=6" } }, - "node_modules/sequelize/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/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" + "chalk": "^2.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=4" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "js-tokens": "^3.0.0 || ^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + "node_modules/loupe": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", + "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "dependencies": { + "get-func-name": "^2.0.0" + } }, - "node_modules/sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", + "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": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.1.0", - "supports-color": "^7.1.0" + "yallist": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" + "engines": { + "node": ">=10" } }, - "node_modules/sinon-chai": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "peerDependencies": { - "chai": "^4.0.0", - "sinon": ">=4.0.0" + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dependencies": { + "es5-ext": "~0.10.2" } }, - "node_modules/sinon/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "engines": { - "node": ">=0.3.1" + "node": ">= 0.6" } }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" + "node_modules/memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" } }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/method-override": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", + "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", "dependencies": { - "has-flag": "^4.0.0" + "debug": "3.1.0", + "methods": "~1.1.2", + "parseurl": "~1.3.2", + "vary": "~1.1.2" }, "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "engines": { - "node": ">= 0.6" + "node_modules/method-override/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "engines": { "node": ">= 0.6" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" }, "engines": { "node": ">=4" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "mime-db": "1.52.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.6" } }, - "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dependencies": { - "ansi-regex": "^3.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "engines": { - "node": ">=4" - } + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "engines": { - "node": ">=0.10.0" + "node_modules/mkdirp": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", - "dev": true, + "node_modules/mocha": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", + "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.4", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" }, "engines": { - "node": ">= 4.0" + "node": ">= 6.0.0" } }, - "node_modules/superagent/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, + "node_modules/mocha/node_modules/debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dependencies": { "ms": "^2.1.1" } }, - "node_modules/superagent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "node_modules/mocha/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", "dev": true }, - "node_modules/supertest": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", - "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - }, + "node_modules/moment": { + "version": "2.29.3", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", + "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", "engines": { - "node": ">=6.0.0" + "node": "*" } }, - "node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "node_modules/moment-timezone": { + "version": "0.5.34", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", + "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", "dependencies": { - "has-flag": "^3.0.0" + "moment": ">= 2.9.0" }, "engines": { - "node": ">=6" + "node": "*" } }, - "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==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "node_modules/swagger-jsdoc": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", - "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", - "dev": true, + "node_modules/mysql2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.0.tgz", + "integrity": "sha512-0t5Ivps5Tdy5YHk5NdKwQhe/4Qyn2pload+S+UooDBvsqngtzujG1BaTWBihQLfeKO3t3122/GtusBtmHEHqww==", "dependencies": { - "commander": "6.2.0", - "doctrine": "3.0.0", - "glob": "7.1.6", - "lodash.mergewith": "^4.6.2", - "swagger-parser": "^10.0.3", - "yaml": "2.0.0-1" - }, - "bin": { - "swagger-jsdoc": "bin/swagger-jsdoc.js" + "denque": "^1.4.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.2", + "long": "^4.0.0", + "lru-cache": "^6.0.0", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" }, "engines": { - "node": ">=12.0.0" + "node": ">= 8.0" } }, - "node_modules/swagger-jsdoc/node_modules/commander": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", - "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", - "dev": true, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/swagger-jsdoc/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, + "node_modules/named-placeholders": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", + "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "lru-cache": "^4.1.3" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=6.0.0" } }, - "node_modules/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", - "dev": true, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dependencies": { - "@apidevtools/swagger-parser": "10.0.3" - }, - "engines": { - "node": ">=10" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, - "node_modules/swagger-ui-dist": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.4.2.tgz", - "integrity": "sha512-vT5QxP/NOr9m4gLZl+SpavWI3M9Fdh30+Sdw9rEtZbkqNmNNEPhjXas2xTD9rsJYYdLzAiMfwXvtooWH3xbLJA==", + "node_modules/named-placeholders/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/swagger-ui-express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", - "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", - "dev": true, - "dependencies": { - "swagger-ui-dist": ">=5.0.0" - }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "engines": { - "node": ">= v0.10.32" - }, - "peerDependencies": { - "express": ">=4.0.0 || >=5.0.0-beta" + "node": ">= 0.6" } }, - "node_modules/timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dependencies": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" + "node_modules/nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" } }, - "node_modules/toposort-class": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + "node_modules/nise/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "engines": { - "node": ">=4" + "node_modules/nise/node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dependencies": { + "isarray": "0.0.1" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" } }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "dependencies": { - "random-bytes": "~1.0.0" + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" }, "engines": { - "node": ">= 0.8" + "node": ">=6" } }, - "node_modules/umzug": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", - "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", - "dependencies": { - "bluebird": "^3.7.2" - }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "engines": { - "node": ">= 4.0.0" + "node": ">= 0.4" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "node_modules/object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node": ">= 0.4" } }, - "node_modules/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "node_modules/object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, "engines": { - "node": ">= 0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", + "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, "engines": { "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/object.groupby": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz", + "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==", + "dev": true, "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.2", + "get-intrinsic": "^1.2.1" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "node_modules/object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dev": true, "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { - "string-width": "^1.0.2 || 2" + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/wkx": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dependencies": { - "@types/node": "*" + "wrappy": "1" } }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "@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" }, "engines": { - "node": ">=6" + "node": ">= 0.8.0" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "p-limit": "^2.0.0" }, "engines": { "node": ">=6" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "dependencies": { - "ansi-regex": "^4.1.0" + "callsites": "^3.0.0" }, "engines": { "node": ">=6" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yaml": { - "version": "2.0.0-1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", - "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", - "dev": true, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "node": ">= 0.8" } }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "node_modules/passport": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", + "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "passport-strategy": "1.x.x", + "pause": "0.0.1" + }, + "engines": { + "node": ">= 0.4.0" } }, - "node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" + "passport-strategy": "1.x.x" }, "engines": { - "node": ">=6" + "node": ">= 0.4.0" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", "engines": { - "node": ">=6" + "node": ">= 0.4.0" } }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/z-schema": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", - "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "dependencies": { - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - }, - "bin": { - "z-schema": "bin/z-schema" - }, "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "commander": "^9.4.1" + "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==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "engines": { + "node": "*" } }, - "node_modules/z-schema/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, - "optional": true, "engines": { - "node": "^12.20.0 || >=14" + "node": ">=6" } - } - }, - "dependencies": { - "@apidevtools/json-schema-ref-parser": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", - "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + }, + "node_modules/pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", "dev": true, - "requires": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - }, "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - } + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + }, + "engines": { + "node": ">=6" } }, - "@apidevtools/openapi-schemas": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", - "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", - "dev": true - }, - "@apidevtools/swagger-methods": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", - "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", - "dev": true - }, - "@apidevtools/swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "requires": { - "@apidevtools/json-schema-ref-parser": "^9.0.6", - "@apidevtools/openapi-schemas": "^2.0.4", - "@apidevtools/swagger-methods": "^3.0.2", - "@jsdevtools/ono": "^7.1.3", - "call-me-maybe": "^1.0.1", - "z-schema": "^5.0.1" + "engines": { + "node": ">= 0.8.0" } }, - "@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "requires": { - "type-detect": "4.0.8" + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "requires": { - "@sinonjs/commons": "^1.7.0" - } + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" }, - "@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" } }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" - }, - "@types/debug": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", - "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", - "requires": { - "@types/ms": "*" + "node_modules/proxyquire": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", + "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", + "dev": true, + "dependencies": { + "fill-keys": "^1.0.2", + "module-not-found-error": "^1.0.1", + "resolve": "^1.11.1" } }, - "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, - "@types/node": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz", - "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==" - }, - "@types/validator": { - "version": "13.7.2", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.2.tgz", - "integrity": "sha512-KFcchQ3h0OPQgFirBRPZr5F/sVjxZsOrQHedj3zi8AH3Zv/hOLx2OLR4hxR5HcfoU+33n69ZuOfzthKVdMoTiw==" - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" } }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.3.tgz", + "integrity": "sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/resolve": { + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "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-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "dependencies": { + "any-promise": "^1.3.0" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/send/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + }, + "node_modules/sequelize": { + "version": "6.6.5", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.6.5.tgz", + "integrity": "sha512-QyRrJrDRiwuiILqTMHUA1yWOPIL12KlfmgZ3hnzQwbMvp2vJ6fzu9bYJQB+qPMosck4mBUggY4Cjoc6Et8FBIQ==", + "dependencies": { + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.13.1", + "lodash": "^4.17.20", + "moment": "^2.26.0", + "moment-timezone": "^0.5.31", + "retry-as-promised": "^3.2.0", + "semver": "^7.3.2", + "sequelize-pool": "^6.0.0", + "toposort-class": "^1.0.1", + "uuid": "^8.1.0", + "validator": "^13.6.0", + "wkx": "^0.5.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependenciesMeta": { + "mariadb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-hstore": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/sequelize-cli": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", + "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", + "dependencies": { + "cli-color": "^1.4.0", + "fs-extra": "^7.0.1", + "js-beautify": "^1.8.8", + "lodash": "^4.17.5", + "resolve": "^1.5.0", + "umzug": "^2.3.0", + "yargs": "^13.1.0" + }, + "bin": { + "sequelize": "lib/sequelize", + "sequelize-cli": "lib/sequelize" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sequelize-pool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", + "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/sequelize-test-helpers": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.2.tgz", + "integrity": "sha512-v7Yy9DKjzFA/OHLtxvFClgN2CKA9cRwxn9+6ha6xoqUzRngXdsbrmle0KD1onSqnCwVIweWlRTLJxcEl1ueozA==", + "dev": true, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/davesag" + }, + "peerDependencies": { + "chai": ">= 4", + "sinon": ">= 10.0.0" + } + }, + "node_modules/sequelize/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/sequelize/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/sequelize/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, + "node_modules/sinon": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", + "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.1.0", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon-chai": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", + "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", + "peerDependencies": { + "chai": "^4.0.0", + "sinon": ">=4.0.0" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.0.tgz", + "integrity": "sha512-jaDqlNSzLtWYW4lvQmU0EnxWMUGQiwHasZl5ZEIwx3S/ijZDjZOzs1y1QqKwKs5vqnFpGtizo4NOYX2s0Voq/g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "eslint": "^8.41.0", + "eslint-config-standard": "17.1.0", + "eslint-config-standard-jsx": "^11.0.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-react": "^7.32.2", + "standard-engine": "^15.0.0", + "version-guard": "^1.1.1" + }, + "bin": { + "standard": "bin/cmd.cjs" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/standard-engine": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.1.0.tgz", + "integrity": "sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "get-stdin": "^8.0.0", + "minimist": "^1.2.6", + "pkg-conf": "^3.1.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/standard/node_modules/eslint-plugin-n": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", + "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", + "dev": true, + "dependencies": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.11.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/standard/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/standard/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/superagent": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", + "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", + "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", + "dev": true, + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.2.0", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.3.5" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/superagent/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/superagent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/supertest": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", + "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^3.8.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dependencies": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "engines": { + "node": ">=4" + } + }, + "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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "dependencies": { + "bluebird": "^3.7.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/version-guard": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.1.tgz", + "integrity": "sha512-MGQLX89UxmYHgDvcXyjBI0cbmoW+t/dANDppNPrno64rYr8nH4SHSuElQuSYdXGEs0mUzdQe1BY+FhVPNsAmJQ==", + "dev": true, + "engines": { + "node": ">=0.10.48" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "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/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@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 + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "@eslint/js": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", + "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "@types/node": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz", + "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" }, "ansi-regex": { "version": "2.1.1", @@ -3465,6 +5890,11 @@ "color-convert": "^1.9.0" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -3473,22 +5903,121 @@ "sprintf-js": "~1.0.2" } }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, + "array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + } + }, + "array.prototype.findlastindex": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", + "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + } + }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, + "asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.3" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3537,6 +6066,26 @@ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, + "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" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -3551,10 +6100,10 @@ "get-intrinsic": "^1.0.2" } }, - "call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, "camelcase": { @@ -3736,6 +6285,28 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -3766,10 +6337,16 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "requires": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" @@ -3857,46 +6434,115 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, "es-abstract": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz", - "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", "requires": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", + "object-inspect": "^1.12.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" }, "dependencies": { "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } } } }, + "es-iterator-helpers": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.13.tgz", + "integrity": "sha512-LK3VGwzvaPWobO8xzXXGRUOGw8Dcjyfk62CsY/wfHN75CwsJPbuypOYJxK6g5RyEL8YDjIWcl6jgd8foO6mmrA==", + "dev": true, + "requires": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.3", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.0", + "safe-array-concat": "^1.0.0" + } + }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + } + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -3941,27 +6587,573 @@ "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", + "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "^8.47.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "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", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "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", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-config-standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", + "dev": true, + "requires": {} + }, + "eslint-config-standard-jsx": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", + "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", + "dev": true, + "requires": {} + }, + "eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "requires": { + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-plugin-es-x": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.2.0.tgz", + "integrity": "sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==", + "dev": true, + "peer": true, + "requires": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.6.0" + } + }, + "eslint-plugin-import": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", + "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "dev": true, + "requires": { + "array-includes": "^3.1.6", + "array.prototype.findlastindex": "^1.2.2", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.8.0", + "has": "^1.0.3", + "is-core-module": "^2.13.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.6", + "object.groupby": "^1.0.0", + "object.values": "^1.1.6", + "semver": "^6.3.1", + "tsconfig-paths": "^3.14.2" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "eslint-plugin-n": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.1.tgz", + "integrity": "sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==", + "dev": true, + "peer": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "builtins": "^5.0.1", + "eslint-plugin-es-x": "^7.1.0", + "ignore": "^5.2.4", + "is-core-module": "^2.12.1", + "minimatch": "^3.1.2", + "resolve": "^1.22.2", + "semver": "^7.5.3" + }, + "dependencies": { + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "peer": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "peer": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "eslint-plugin-promise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", + "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", + "dev": true, + "requires": {} + }, + "eslint-plugin-react": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "dev": true, + "requires": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "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==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } } }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "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 }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -4127,6 +7319,42 @@ "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", @@ -4177,6 +7405,30 @@ "is-buffer": "~2.0.3" } }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "form-data": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", @@ -4224,6 +7476,22 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, "generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -4243,15 +7511,22 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" } }, + "get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true + }, "get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -4274,11 +7549,51 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "requires": { + "define-properties": "^1.1.3" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", @@ -4293,9 +7608,9 @@ } }, "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" }, "has-flag": { "version": "3.0.0", @@ -4310,6 +7625,11 @@ "get-intrinsic": "^1.1.1" } }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -4355,10 +7675,32 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, "inflection": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz", - "integrity": "sha512-cmZlljCRTBFouT8UzMzrGcVEvkv6D/wBdcdKG7J1QH5cXjtU75Dm+P27v9EKu/Y43UYyCJd1WC4zLebRrC8NBw==" + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz", + "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==" }, "inflight": { "version": "1.0.6", @@ -4380,11 +7722,11 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "requires": { - "get-intrinsic": "^1.1.0", + "get-intrinsic": "^1.2.0", "has": "^1.0.3", "side-channel": "^1.0.4" } @@ -4394,6 +7736,31 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -4417,14 +7784,14 @@ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" }, "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" }, "is-core-module": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", - "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", "requires": { "has": "^1.0.3" } @@ -4437,11 +7804,50 @@ "has-tostringtag": "^1.0.0" } }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true + }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -4461,6 +7867,12 @@ "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", "dev": true }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -4480,6 +7892,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true + }, "is-shared-array-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", @@ -4504,6 +7922,20 @@ "has-symbols": "^1.0.2" } }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "requires": { + "which-typed-array": "^1.1.11" + } + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -4512,6 +7944,16 @@ "call-bind": "^1.0.2" } }, + "is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -4523,6 +7965,19 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "iterator.prototype": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.0.tgz", + "integrity": "sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "has-tostringtag": "^1.0.0", + "reflect.getprototypeof": "^1.0.3" + } + }, "js-beautify": { "version": "1.14.3", "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", @@ -4534,6 +7989,12 @@ "nopt": "^5.0.0" } }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -4543,6 +8004,33 @@ "esprima": "^4.0.0" } }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -4551,11 +8039,68 @@ "graceful-fs": "^4.1.6" } }, + "jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "requires": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "dependencies": { + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + } + } + }, "just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + }, + "dependencies": { + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -4575,16 +8120,10 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "dev": true - }, - "lodash.mergewith": { + "lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, "log-symbols": { @@ -4600,6 +8139,15 @@ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "loupe": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", @@ -4609,11 +8157,11 @@ } }, "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "requires": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" } }, "lru-queue": { @@ -4784,26 +8332,26 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mysql2": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.7.0.tgz", - "integrity": "sha512-xTWWQPjP5rcrceZQ7CSTKR/4XIDeH/cRkNH/uzvVGQ7W5c7EJ0dXeJUusk7OKhIoHj7uFKUxDVSCfLIl+jluog==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.0.tgz", + "integrity": "sha512-0t5Ivps5Tdy5YHk5NdKwQhe/4Qyn2pload+S+UooDBvsqngtzujG1BaTWBihQLfeKO3t3122/GtusBtmHEHqww==", "requires": { "denque": "^1.4.1", "generate-function": "^2.3.1", - "iconv-lite": "^0.5.0", + "iconv-lite": "^0.6.2", "long": "^4.0.0", - "lru-cache": "^5.1.1", + "lru-cache": "^6.0.0", "named-placeholders": "^1.1.2", "seq-queue": "^0.0.5", - "sqlstring": "^2.3.1" + "sqlstring": "^2.3.2" }, "dependencies": { "iconv-lite": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", - "integrity": "sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" } } } @@ -4832,6 +8380,12 @@ } } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, "negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -4886,10 +8440,16 @@ "abbrev": "1" } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" }, "object-keys": { "version": "1.1.1", @@ -4907,14 +8467,69 @@ "object-keys": "^1.0.11" } }, + "object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, "object.getownpropertydescriptors": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.groupby": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz", + "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.2", + "get-intrinsic": "^1.2.1" + } + }, + "object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dev": true, + "requires": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "on-finished": { @@ -4938,12 +8553,19 @@ "wrappy": "1" } }, - "openapi-types": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", - "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", "dev": true, - "peer": true + "requires": { + "@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" + } }, "p-limit": { "version": "2.3.0", @@ -4966,6 +8588,25 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -5003,6 +8644,12 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -5023,10 +8670,27 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" }, - "pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true }, "process-nextick-args": { "version": "2.0.1", @@ -5034,6 +8698,17 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -5064,6 +8739,12 @@ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true + }, "qs": { "version": "6.10.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", @@ -5072,6 +8753,12 @@ "side-channel": "^1.0.4" } }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -5093,6 +8780,12 @@ "unpipe": "1.0.0" } }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -5116,6 +8809,36 @@ } } }, + "reflect.getprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.3.tgz", + "integrity": "sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + } + }, + "regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5127,25 +8850,86 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", + "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", "requires": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, "retry-as-promised": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-5.0.0.tgz", - "integrity": "sha512-6S+5LvtTl2ggBumk04hBo/4Uf6fRJUwIgunGZ7CYEBCeufGFW1Pu6ucUf/UskHeWOIsUcLOGLFXPig5tR5V1nA==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "requires": { + "any-promise": "^1.3.0" + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + } + } }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -5219,25 +9003,22 @@ "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" }, "sequelize": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.19.0.tgz", - "integrity": "sha512-B3oGIdpYBERDjRDm74h7Ky67f6ZLcmBXOA7HscYObiOSo4pD7VBc9mtm44wNV7unc0uk8I1d30nbZBTQCE377A==", - "requires": { - "@types/debug": "^4.1.7", - "@types/validator": "^13.7.1", - "debug": "^4.3.3", - "dottie": "^2.0.2", - "inflection": "^1.13.2", - "lodash": "^4.17.21", - "moment": "^2.29.1", - "moment-timezone": "^0.5.34", - "pg-connection-string": "^2.5.0", - "retry-as-promised": "^5.0.0", - "semver": "^7.3.5", - "sequelize-pool": "^7.1.0", + "version": "6.6.5", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.6.5.tgz", + "integrity": "sha512-QyRrJrDRiwuiILqTMHUA1yWOPIL12KlfmgZ3hnzQwbMvp2vJ6fzu9bYJQB+qPMosck4mBUggY4Cjoc6Et8FBIQ==", + "requires": { + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.13.1", + "lodash": "^4.17.20", + "moment": "^2.26.0", + "moment-timezone": "^0.5.31", + "retry-as-promised": "^3.2.0", + "semver": "^7.3.2", + "sequelize-pool": "^6.0.0", "toposort-class": "^1.0.1", - "uuid": "^8.3.2", - "validator": "^13.7.0", + "uuid": "^8.1.0", + "validator": "^13.6.0", "wkx": "^0.5.0" }, "dependencies": { @@ -5249,14 +9030,6 @@ "ms": "2.1.2" } }, - "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==", - "requires": { - "yallist": "^4.0.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -5269,33 +9042,27 @@ "requires": { "lru-cache": "^6.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, "sequelize-cli": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-5.5.1.tgz", - "integrity": "sha512-ZM4kUZvY3y14y+Rq3cYxGH7YDJz11jWHcN2p2x7rhAIemouu4CEXr5ebw30lzTBtyXV4j2kTO+nUjZOqzG7k+Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", + "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", "requires": { - "bluebird": "^3.5.3", "cli-color": "^1.4.0", "fs-extra": "^7.0.1", "js-beautify": "^1.8.8", "lodash": "^4.17.5", "resolve": "^1.5.0", - "umzug": "^2.1.0", + "umzug": "^2.3.0", "yargs": "^13.1.0" } }, "sequelize-pool": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", - "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", + "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==" }, "sequelize-test-helpers": { "version": "1.4.2", @@ -5325,6 +9092,21 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -5389,6 +9171,71 @@ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" }, + "standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.0.tgz", + "integrity": "sha512-jaDqlNSzLtWYW4lvQmU0EnxWMUGQiwHasZl5ZEIwx3S/ijZDjZOzs1y1QqKwKs5vqnFpGtizo4NOYX2s0Voq/g==", + "dev": true, + "requires": { + "eslint": "^8.41.0", + "eslint-config-standard": "17.1.0", + "eslint-config-standard-jsx": "^11.0.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-n": "^15.7.0", + "eslint-plugin-promise": "^6.1.1", + "eslint-plugin-react": "^7.32.2", + "standard-engine": "^15.0.0", + "version-guard": "^1.1.1" + }, + "dependencies": { + "eslint-plugin-n": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", + "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", + "dev": true, + "requires": { + "builtins": "^5.0.1", + "eslint-plugin-es": "^4.1.0", + "eslint-utils": "^3.0.0", + "ignore": "^5.1.1", + "is-core-module": "^2.11.0", + "minimatch": "^3.1.2", + "resolve": "^1.22.1", + "semver": "^7.3.8" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "standard-engine": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.1.0.tgz", + "integrity": "sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==", + "dev": true, + "requires": { + "get-stdin": "^8.0.0", + "minimist": "^1.2.6", + "pkg-conf": "^3.1.0", + "xdg-basedir": "^4.0.0" + } + }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -5420,22 +9267,50 @@ "strip-ansi": "^4.0.0" } }, + "string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + } + }, + "string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "strip-ansi": { @@ -5453,6 +9328,12 @@ } } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -5516,66 +9397,12 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, - "swagger-jsdoc": { - "version": "6.2.8", - "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", - "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", - "dev": true, - "requires": { - "commander": "6.2.0", - "doctrine": "3.0.0", - "glob": "7.1.6", - "lodash.mergewith": "^4.6.2", - "swagger-parser": "^10.0.3", - "yaml": "2.0.0-1" - }, - "dependencies": { - "commander": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", - "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "swagger-parser": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", - "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", - "dev": true, - "requires": { - "@apidevtools/swagger-parser": "10.0.3" - } - }, - "swagger-ui-dist": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.4.2.tgz", - "integrity": "sha512-vT5QxP/NOr9m4gLZl+SpavWI3M9Fdh30+Sdw9rEtZbkqNmNNEPhjXas2xTD9rsJYYdLzAiMfwXvtooWH3xbLJA==", + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "swagger-ui-express": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", - "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", - "dev": true, - "requires": { - "swagger-ui-dist": ">=5.0.0" - } - }, "timers-ext": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", @@ -5595,16 +9422,43 @@ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, + "tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, + "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 + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -5614,6 +9468,49 @@ "mime-types": "~2.1.24" } }, + "typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, "uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -5631,13 +9528,13 @@ } }, "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, @@ -5651,6 +9548,15 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5677,6 +9583,12 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "version-guard": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.1.tgz", + "integrity": "sha512-MGQLX89UxmYHgDvcXyjBI0cbmoW+t/dANDppNPrno64rYr8nH4SHSuElQuSYdXGEs0mUzdQe1BY+FhVPNsAmJQ==", + "dev": true + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -5697,11 +9609,63 @@ "is-symbol": "^1.0.3" } }, + "which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "requires": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -5758,21 +9722,21 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "yaml": { - "version": "2.0.0-1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", - "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { "version": "13.3.2", @@ -5835,26 +9799,11 @@ "yargs": "^13.3.0" } }, - "z-schema": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", - "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", - "dev": true, - "requires": { - "commander": "^9.4.1", - "lodash.get": "^4.4.2", - "lodash.isequal": "^4.5.0", - "validator": "^13.7.0" - }, - "dependencies": { - "commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "optional": true - } - } + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index f03080cb39..d2759c1bdf 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "test", "version": "1.0.0", - "description": "", "main": "index.js", "scripts": { "start": "NODE_ENV=development node app.js", "dev": "NODE_ENV=development nodemon app.js", + "lint": "eslint \"**/*.js\" --fix", "test": "mocha test --exit --recursive --timeout 5000" }, "author": "", @@ -20,19 +20,23 @@ "faker": "^4.1.0", "method-override": "^3.0.0", "mocha": "^6.0.2", - "mysql2": "^1.6.4", + "mysql2": "^2.3.0", "passport": "^0.4.0", "passport-local": "^1.0.0", - "sequelize": "^6.18.0", - "sequelize-cli": "^5.5.0", + "sequelize": "^6.6.5", + "sequelize-cli": "^6.2.0", "sinon": "^10.0.0", "sinon-chai": "^3.3.0" }, "devDependencies": { + "eslint-config-standard": "^17.1.0", "proxyquire": "^2.1.3", "sequelize-test-helpers": "^1.4.2", - "supertest": "^3.3.0", - "swagger-jsdoc": "^6.2.8", - "swagger-ui-express": "^5.0.0" - } + "standard": "*", + "supertest": "^3.3.0" + }, + "directories": { + "test": "test" + }, + "description": "" } From a9f1d7023c74e59410fbf210440bf200f977fbec Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sun, 20 Aug 2023 21:53:27 +0800 Subject: [PATCH 004/170] fix: uppercase for models --- models/like.js | 5 +++-- models/reply.js | 4 ++-- models/tweet.js | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/models/like.js b/models/like.js index 722a28d70b..de23092608 100644 --- a/models/like.js +++ b/models/like.js @@ -14,8 +14,9 @@ module.exports = (sequelize, DataTypes) => { } }; Like.init({ - userId: DataTypes.INTEGER, - tweetId: DataTypes.INTEGER + // 首字大寫為了過測試 + UserId: DataTypes.INTEGER, + TweetId: DataTypes.INTEGER }, { sequelize, modelName: 'Like', diff --git a/models/reply.js b/models/reply.js index dad239fc0a..b8467cf3a7 100644 --- a/models/reply.js +++ b/models/reply.js @@ -15,8 +15,8 @@ module.exports = (sequelize, DataTypes) => { }; Reply.init({ comment: DataTypes.TEXT, - userId: DataTypes.INTEGER, - tweetId: DataTypes.INTEGER + UserId: DataTypes.INTEGER, + TweetId: DataTypes.INTEGER }, { sequelize, modelName: 'Reply', diff --git a/models/tweet.js b/models/tweet.js index 8a6ac8ba13..d769b646bc 100644 --- a/models/tweet.js +++ b/models/tweet.js @@ -15,7 +15,7 @@ module.exports = (sequelize, DataTypes) => { }; Tweet.init({ description: DataTypes.TEXT, - userId: DataTypes.INTEGER + UserId: DataTypes.INTEGER }, { sequelize, modelName: 'Tweet', From 6a0cd9a6df79d43d049d7fcfba09dec6d93a056e Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sun, 20 Aug 2023 22:23:27 +0800 Subject: [PATCH 005/170] feat: add associations between models --- models/like.js | 2 ++ models/reply.js | 2 ++ models/tweet.js | 2 ++ models/user.js | 13 +++++++++++++ 4 files changed, 19 insertions(+) diff --git a/models/like.js b/models/like.js index de23092608..f6101a8da3 100644 --- a/models/like.js +++ b/models/like.js @@ -11,6 +11,8 @@ module.exports = (sequelize, DataTypes) => { */ static associate (models) { // define association here + Like.belongsTo(models.User, { foreignKey: 'userId' }) + Like.belongsTo(models.Tweet, { foreignKey: 'tweetId' }) } }; Like.init({ diff --git a/models/reply.js b/models/reply.js index b8467cf3a7..6fd0fef860 100644 --- a/models/reply.js +++ b/models/reply.js @@ -11,6 +11,8 @@ module.exports = (sequelize, DataTypes) => { */ static associate (models) { // define association here + Reply.belongsTo(models.User, { foreignKey: 'userId' }) + Reply.belongsTo(models.Tweet, { foreignKey: 'tweetId' }) } }; Reply.init({ diff --git a/models/tweet.js b/models/tweet.js index d769b646bc..8de1f496b0 100644 --- a/models/tweet.js +++ b/models/tweet.js @@ -11,6 +11,8 @@ module.exports = (sequelize, DataTypes) => { */ static associate (models) { // define association here + Tweet.hasMany(models.Reply, { foreignKey: 'tweetId' }) + Tweet.hasMany(models.Like, { foreignKey: 'tweetId' }) } }; Tweet.init({ diff --git a/models/user.js b/models/user.js index 5f05801375..74c077701c 100644 --- a/models/user.js +++ b/models/user.js @@ -11,6 +11,19 @@ module.exports = (sequelize, DataTypes) => { */ static associate (models) { // define association here + User.hasMany(models.Tweet, { foreignKey: 'userId' }) + User.hasMany(models.Reply, { foreignKey: 'userId' }) + User.hasMany(models.Like, { foreignKey: 'userId' }) + User.belongsToMany(models.User, { + through: models.Followship, + foreignKey: 'followerId', + as: 'Followings' + }) + User.belongsToMany(models.User, { + through: models.Followship, + foreignKey: 'followingId', + as: 'Followers' + }) } }; User.init({ From c3bbe6f56cf7f059a63e96a747d3190a7afce53a Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 21 Aug 2023 16:28:13 +0800 Subject: [PATCH 006/170] chore: add user, tweet, reply seeder file --- _helpers.js | 9 +- app.js | 16 +- config/passport.js | 4 +- controllers/apis/admin-controller.js | 157 ++++ controllers/apis/user-controller.js | 21 + package-lock.json | 765 +++++++++++++++++++- package.json | 4 +- routes/index.js | 17 + routes/modules/admin.js | 9 + seeders/20230821044414-users-seed-file.js | 53 ++ seeders/20230821074916-tweets-seed-file.js | 24 + seeders/20230821081029-replies-seed-file.js | 39 + services/admin-services.js | 0 services/followship-services.js | 0 services/reply-services.js | 0 services/tweet-services.js | 0 services/user-services.js | 0 test/models/Followship.spec.js | 9 +- test/models/Like.spec.js | 46 +- test/models/Reply.spec.js | 48 +- test/models/Tweet.spec.js | 48 +- test/models/User.spec.js | 28 +- test/requests/admin.spec.js | 125 ++-- test/requests/followship.spec.js | 124 ++-- test/requests/like.spec.js | 134 ++-- test/requests/reply.spec.js | 142 ++-- test/requests/tweet.spec.js | 144 ++-- test/requests/user.spec.js | 460 ++++++------ 28 files changed, 1699 insertions(+), 727 deletions(-) create mode 100644 seeders/20230821044414-users-seed-file.js create mode 100644 seeders/20230821074916-tweets-seed-file.js create mode 100644 seeders/20230821081029-replies-seed-file.js delete mode 100644 services/admin-services.js delete mode 100644 services/followship-services.js delete mode 100644 services/reply-services.js delete mode 100644 services/tweet-services.js delete mode 100644 services/user-services.js diff --git a/_helpers.js b/_helpers.js index b7a88770e8..d83196d1fb 100644 --- a/_helpers.js +++ b/_helpers.js @@ -1,8 +1,7 @@ - -function getUser(req) { - return req.user; +function getUser (req) { + return req.user } module.exports = { - getUser, -}; \ No newline at end of file + getUser +} diff --git a/app.js b/app.js index a1980c675d..b27cc6744a 100644 --- a/app.js +++ b/app.js @@ -1,15 +1,15 @@ -const express = require("express"); -const helpers = require("./_helpers"); +const express = require('express') +const helpers = require('./_helpers') -const app = express(); -const port = 3000; +const app = express() +const port = 3000 // use helpers.getUser(req) to replace req.user -function authenticated(req, res, next) { +function authenticated (req, res, next) { // passport.authenticate('jwt', { ses... } -app.get("/", (req, res) => res.send("Hello World!")); -app.listen(port, () => console.log(`Example app listening on port ${port}!`)); +app.get('/', (req, res) => res.send('Hello World!')) +app.listen(port, () => console.log(`Example app listening on port ${port}!`)) -module.exports = app; +module.exports = app diff --git a/config/passport.js b/config/passport.js index a2298f8964..4ca5eefed6 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,5 +1,3 @@ const passport = require('passport') - - -module.exports = passport \ No newline at end of file +module.exports = passport diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index e69de29bb2..8038b06510 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -0,0 +1,157 @@ +const db = require('../../models') +const { User, Tweet, Reply, Like } = db +const bcrypt = require('bcrypt-nodejs') +const jwt = require('jsonwebtoken') +const defaultLimit = 10 + +const adminController = { + getUsers: (req, res) => { + const options = { + limit: +req.query.limit || defaultLimit, + offset: +req.query.offset || 0, + raw: true, + order: [['tweetNum', 'desc']], + attributes: { + exclude: [ + 'email', + 'introduction', + 'password', + 'lastLoginAt', + 'updatedAt', + 'createdAt' + ] + }, + where: { role: 'user' } + } + User.findAll(options) + .then(users => { + users.forEach(user => { + if (user.introduction) { + user.introduction = user.introduction.substring(0, 50) + } + }) + res.status(200).json(users) + }) + .catch(error => { + res.status(500).json({ + status: 'error', + message: error + }) + }) + }, + getTweets: (req, res) => { + const options = { + limit: +req.query.limit || defaultLimit, + offset: +req.query.offset || 0, + attributes: ['id', 'description', 'likeNum', 'replyNum', 'createdAt'], + order: [['createdAt', 'desc']], + include: [ + { + model: User, + attributes: ['id', 'account', 'name', 'avatar'], + as: 'Author' + } + ] + } + Tweet.findAll(options) + .then(tweets => { + tweets.forEach(tweet => { + tweet.description = tweet.description.substring(0, 50) + }) + return res.status(200).json(tweets) + }) + .catch(() => + res.status(500).json({ + status: 'error', + message: error + }) + ) + }, + deleteTweet: (req, res) => { + const options = { + include: [ + { model: Reply, attributes: ['id'], raw: true }, + { model: Like, attributes: ['id', 'UserId'] } + ] + } + Tweet.findByPk(+req.params.tweetId, options) + .then(async tweet => { + await tweet.destroy() + await User.decrement({ tweetNum: 1 }, { where: { id: tweet.UserId } }) + if (tweet.Replies.length) { + await Reply.destroy({ + where: { id: tweet.Replies.map(reply => reply.id) } + }) + } + if (tweet.Likes.length) { + await Like.destroy({ + where: { id: tweet.Likes.map(like => like.id) } + }) + await User.decrement( + { likeNum: 1 }, + { where: { id: tweet.Likes.map(like => like.UserId) } } + ) + } + res.status(200).json({ + status: 'success', + message: 'Successfully delete tweet.' + }) + }) + .catch(error => + res.status(500).json({ + status: 'error', + message: error + }) + ) + }, + login: (req, res) => { + const { password, email } = req.body + if (!password || !email) { + return res.status(400).json({ + status: 'error', + message: 'Password or email can not be empty.' + }) + } + + User.findOne({ where: { email, role: 'admin' } }) + .then(user => { + if (!user) { + return res.status(401).json({ + status: 'error', + message: "This admin account doesn't exist." + }) + } + if (!bcrypt.compareSync(password, user.password)) { + return res.status(401).json({ + status: 'error', + message: 'Password incorrect.' + }) + } + + const payload = { + id: user.id + } + const token = jwt.sign(payload, 'numberFive') + return res.status(200).json({ + status: 'success', + message: 'Administrator successfully login.', + token, + User: { + id: user.id, + name: user.name, + account: user.account, + email: user.email, + role: user.role + } + }) + }) + .catch(error => + res.status(500).json({ + status: 'error', + message: error + }) + ) + } +} + +module.exports = adminController diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index e69de29bb2..a153a32c2c 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -0,0 +1,21 @@ +const bcrypt = require('bcryptjs') +const db = require('../models') +const { User } = db +const userController = { + signUp: (req, res) => { + bcrypt + .hash(req.body.password, 10) + .then(hash => + User.create({ + account: req.body.account, + name: req.body.name, + email: req.body.email, + password: hash + }) + ) + .then(() => { + res.redirect('api/users/signin') + }) + } +} +module.exports = userController diff --git a/package-lock.json b/package-lock.json index ac576c6e54..f33df23f6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,15 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "bcrypt": "^5.1.1", "bcrypt-nodejs": "0.0.3", + "bcryptjs": "^2.4.3", "body-parser": "^1.18.3", "chai": "^4.2.0", "connect-flash": "^0.1.1", "express": "^4.16.4", "express-session": "^1.15.6", - "faker": "^4.1.0", + "faker": "^5.5.3", "method-override": "^3.0.0", "mocha": "^6.0.2", "mysql2": "^2.3.0", @@ -232,6 +234,39 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -347,6 +382,38 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -395,6 +462,36 @@ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, + "node_modules/aproba": { + "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==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -565,12 +662,30 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/bcrypt-nodejs": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=", "deprecated": "bcrypt-nodejs is no longer actively maintained. Please use bcrypt or bcryptjs. See https://github.com/kelektiv/node.bcrypt.js/wiki/bcrypt-vs-brypt.js to learn more about these two options" }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -723,6 +838,14 @@ "node": "*" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/cli-color": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", @@ -791,6 +914,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -836,6 +967,11 @@ "node": ">= 0.4.0" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -975,6 +1111,11 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/denque": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", @@ -1000,6 +1141,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, "node_modules/diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -2254,9 +2403,9 @@ "dev": true }, "node_modules/faker": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", - "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", + "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==" }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -2440,6 +2589,28 @@ "node": ">=6 <7 || >=8" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2475,6 +2646,70 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -2701,6 +2936,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2732,6 +2972,39 @@ "node": ">= 0.8" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3429,6 +3702,28 @@ "es5-ext": "~0.10.2" } }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -3533,6 +3828,37 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/mkdirp": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", @@ -3724,6 +4050,11 @@ "isarray": "0.0.1" } }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, "node_modules/node-environment-flags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", @@ -3733,6 +4064,25 @@ "semver": "^5.7.0" } }, + "node_modules/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -3747,11 +4097,21 @@ "node": ">=6" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4353,7 +4713,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -4713,6 +5072,11 @@ "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/sinon": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", @@ -4909,7 +5273,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -4917,8 +5280,7 @@ "node_modules/string_decoder/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/string-width": { "version": "2.1.1", @@ -5101,6 +5463,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5129,6 +5518,11 @@ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -5315,8 +5709,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "node_modules/utils-merge": { "version": "1.0.1", @@ -5359,6 +5752,20 @@ "node": ">=0.10.48" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -5765,6 +6172,32 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5860,6 +6293,29 @@ "dev": true, "requires": {} }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -5895,6 +6351,32 @@ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, + "aproba": { + "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==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -6023,11 +6505,25 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + } + }, "bcrypt-nodejs": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -6150,6 +6646,11 @@ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, "cli-color": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", @@ -6211,6 +6712,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -6250,6 +6756,11 @@ "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -6358,6 +6869,11 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "denque": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", @@ -6373,6 +6889,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==" + }, "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -7315,9 +7836,9 @@ "dev": true }, "faker": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", - "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", + "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==" }, "fast-deep-equal": { "version": "3.1.3", @@ -7466,6 +7987,24 @@ "universalify": "^0.1.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -7492,6 +8031,57 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -7643,6 +8233,11 @@ "has-symbols": "^1.0.2" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -7667,6 +8262,30 @@ } } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -8172,6 +8791,21 @@ "es5-ext": "~0.10.2" } }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -8254,6 +8888,30 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "mkdirp": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", @@ -8423,6 +9081,11 @@ } } }, + "node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, "node-environment-flags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", @@ -8432,6 +9095,14 @@ "semver": "^5.7.0" } }, + "node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -8440,11 +9111,21 @@ "abbrev": "1" } }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, "object-inspect": { "version": "1.12.3", @@ -8883,7 +9564,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -9122,6 +9802,11 @@ "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "sinon": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", @@ -9245,7 +9930,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, "requires": { "safe-buffer": "~5.1.0" }, @@ -9253,8 +9937,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -9397,6 +10080,26 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, + "tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -9422,6 +10125,11 @@ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -9560,8 +10268,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { "version": "1.0.1", @@ -9589,6 +10296,20 @@ "integrity": "sha512-MGQLX89UxmYHgDvcXyjBI0cbmoW+t/dANDppNPrno64rYr8nH4SHSuElQuSYdXGEs0mUzdQe1BY+FhVPNsAmJQ==", "dev": true }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index d2759c1bdf..9479bb34e3 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,15 @@ "author": "", "license": "ISC", "dependencies": { + "bcrypt": "^5.1.1", "bcrypt-nodejs": "0.0.3", + "bcryptjs": "^2.4.3", "body-parser": "^1.18.3", "chai": "^4.2.0", "connect-flash": "^0.1.1", "express": "^4.16.4", "express-session": "^1.15.6", - "faker": "^4.1.0", + "faker": "^5.5.3", "method-override": "^3.0.0", "mocha": "^6.0.2", "mysql2": "^2.3.0", diff --git a/routes/index.js b/routes/index.js index e69de29bb2..0fb6d68530 100644 --- a/routes/index.js +++ b/routes/index.js @@ -0,0 +1,17 @@ +const express = require('express') +const router = express.Router() +const userController = require('../controllers/user-controller') +const admin = require('./modules/admin') + +// api/admin +router.use('/api/admin', admin) +// api/users +router.get('/api/users', userController.getUsers) +router.get('/api/signup', userController.signUpPage) +router.post('/api/signup', userController.signUp) + +// api/tweets +// router.get("/restaurants", restController.getRestaurants); +// router.use("/", (req, res) => res.redirect("/restaurants")); + +module.exports = router diff --git a/routes/modules/admin.js b/routes/modules/admin.js index e69de29bb2..56b56d14f6 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -0,0 +1,9 @@ +const express = require('express') +const router = express.Router() +const adminController = require('../../controllers/admin-controller') +router.post('/signIn', adminController.signIn) +router.get('/users', adminController.getUsers) +router.delete('/tweets/:id', adminController.deleteTweet) +router.get('/tweets', adminController.getTweets) +router.use('/', (req, res) => res.redirect('api/admin/users')) +module.exports = router diff --git a/seeders/20230821044414-users-seed-file.js b/seeders/20230821044414-users-seed-file.js new file mode 100644 index 0000000000..3364ace0b8 --- /dev/null +++ b/seeders/20230821044414-users-seed-file.js @@ -0,0 +1,53 @@ +'use strict' +const bcrypt = require('bcrypt') +const faker = require('faker') + +module.exports = { + up: async (queryInterface, Sequelize) => { + // 新增:依照DOD需求的兩個測試帳號 + await queryInterface.bulkInsert( + 'Users', + [ + { + id: 1, + email: 'root@example.com', + password: await bcrypt.hash('12345678', 10), + role: 'admin', + name: 'Admin', + account: 'root', + avatar: `https://loremflickr.com/320/240/man/?random=${ + Math.random() * 100 + }`, + cover: `https://loremflickr.com/1440/480/city/?random=${ + Math.random() * 100 + }`, + introduction: faker.lorem.text().substring(0, 160), + created_at: new Date(), + updated_at: new Date() + }, + { + id: 2, + email: 'user1@example.com', + password: await bcrypt.hash('12345678', 10), + role: 'user', + name: 'User1', + account: 'user1', + avatar: `https://loremflickr.com/320/240/man/?random=${ + Math.random() * 100 + }`, + cover: `https://loremflickr.com/1440/480/city/?random=${ + Math.random() * 100 + }`, + introduction: faker.lorem.text().substring(0, 160), + created_at: new Date(), + updated_at: new Date() + } + ], + {} + ) + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Users', {}) + } +} diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js new file mode 100644 index 0000000000..96153a2138 --- /dev/null +++ b/seeders/20230821074916-tweets-seed-file.js @@ -0,0 +1,24 @@ +'use strict' +const faker = require('faker') + +module.exports = { + up: async (queryInterface, Sequelize) => { + const data = [] + Array.from({ length: 5 }).map((user, i) => { + for (let j = 0; j < 10; ++j) { + data.push({ + id: j * 10 + i + 1, + description: faker.lorem.text(140), + createdAt: new Date(), + updatedAt: new Date(), + UserId: i + 1 + }) + } + }) + await queryInterface.bulkInsert('Tweets', data, {}) + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Tweets', {}) + } +} diff --git a/seeders/20230821081029-replies-seed-file.js b/seeders/20230821081029-replies-seed-file.js new file mode 100644 index 0000000000..198aa6224c --- /dev/null +++ b/seeders/20230821081029-replies-seed-file.js @@ -0,0 +1,39 @@ +"use strict"; +const faker = require("faker"); +const db = require("../models"); +const User = db.User; +const Tweet = db.Tweet; +module.exports = { + up: async (queryInterface, Sequelize) => { + const userData = await User.findAll({ + raw: true, + nest: true, + where: { role: "user" }, + attributes: ["id"], + }); + const tweetData = await Tweet.findAll({ + raw: true, + nest: true, + attributes: ["id"], + }); + + await queryInterface.bulkInsert( + "Replies", + Array.from({ length: 150 }).map((d, i) => { + const tweet = { + TweetId: tweetData[Math.floor(i / 3)].id, + UserId: userData[Math.floor(Math.random() * userData.length)].id, + comment: faker.lorem.text(), + createdAt: new Date(), + updatedAt: new Date(), + }; + return tweet; + }), + {} + ); + }, + + down: async (queryInterface, Sequelize) => { + return queryInterface.bulkDelete("Replies", null, {}); + }, +}; diff --git a/services/admin-services.js b/services/admin-services.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/followship-services.js b/services/followship-services.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/reply-services.js b/services/reply-services.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/tweet-services.js b/services/tweet-services.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/user-services.js b/services/user-services.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/models/Followship.spec.js b/test/models/Followship.spec.js index 893356fc55..f9c89b9282 100644 --- a/test/models/Followship.spec.js +++ b/test/models/Followship.spec.js @@ -1,7 +1,7 @@ -const chai = require('chai'); -const sinon = require('sinon'); -const proxyquire = require('proxyquire'); -chai.use(require('sinon-chai')); +const chai = require('chai') +const sinon = require('sinon') +const proxyquire = require('proxyquire') +chai.use(require('sinon-chai')) const { expect } = require('chai') const { @@ -39,5 +39,4 @@ describe('# Followship Model', () => { } ) }) - }) diff --git a/test/models/Like.spec.js b/test/models/Like.spec.js index 2d4f3ef3ce..ac7790fb49 100644 --- a/test/models/Like.spec.js +++ b/test/models/Like.spec.js @@ -1,7 +1,7 @@ -const chai = require('chai'); -const sinon = require('sinon'); -const proxyquire = require('proxyquire'); -chai.use(require('sinon-chai')); +const chai = require('chai') +const sinon = require('sinon') +const proxyquire = require('proxyquire') +chai.use(require('sinon-chai')) const { expect } = require('chai') const { @@ -52,12 +52,12 @@ describe('# Like Model', () => { Like.associate({ Tweet }) }) - it('should belong to user', (done) => { + it('should belong to user', done => { // 檢查是否有呼叫 belongsTo(User) expect(Like.belongsTo).to.have.been.calledWith(User) done() }) - it('should belong to tweet', (done) => { + it('should belong to tweet', done => { // 檢查是否有呼叫 belongsTo(Tweet) expect(Like.belongsTo).to.have.been.calledWith(Tweet) done() @@ -66,41 +66,39 @@ describe('# Like Model', () => { // 檢查 model 的新增、修改、刪除、更新 context('action', () => { - let data = null // 檢查 db.Like 是否真的可以新增一筆資料 - it('create', (done) => { - db.Like.create({}).then((like) => { + it('create', done => { + db.Like.create({}).then(like => { data = like done() }) }) // 檢查 db.Like 是否真的可以讀取一筆資料 - it('read', (done) => { - db.Like.findByPk(data.id).then((like) => { - expect(data.id).to.be.equal(like.id) - done() - }) + it('read', done => { + db.Like.findByPk(data.id).then(like => { + expect(data.id).to.be.equal(like.id) + done() + }) }) // 檢查 db.Like 是否真的可以更新一筆資料 - it('update', (done) => { - db.Like.update({}, { where: { id: data.id }}).then(() => { - db.Like.findByPk(data.id).then((like) => { - expect(data.updatedAt).to.be.not.equal(like.updatedAt) + it('update', done => { + db.Like.update({}, { where: { id: data.id } }).then(() => { + db.Like.findByPk(data.id).then(like => { + expect(data.updatedAt).to.be.not.equal(like.updatedAt) done() }) }) }) - // 檢查 db.Like 是否真的可以刪除一筆資料 - it('delete', (done) => { - db.Like.destroy({ where: { id: data.id }}).then(() => { - db.Like.findByPk(data.id).then((like) => { - expect(like).to.be.equal(null) + // 檢查 db.Like 是否真的可以刪除一筆資料 + it('delete', done => { + db.Like.destroy({ where: { id: data.id } }).then(() => { + db.Like.findByPk(data.id).then(like => { + expect(like).to.be.equal(null) done() }) }) }) }) - }) diff --git a/test/models/Reply.spec.js b/test/models/Reply.spec.js index 33c1ba0443..f85aa0fc9e 100644 --- a/test/models/Reply.spec.js +++ b/test/models/Reply.spec.js @@ -1,7 +1,7 @@ -const chai = require('chai'); -const sinon = require('sinon'); -const proxyquire = require('proxyquire'); -chai.use(require('sinon-chai')); +const chai = require('chai') +const sinon = require('sinon') +const proxyquire = require('proxyquire') +chai.use(require('sinon-chai')) const { expect } = require('chai') const { @@ -37,13 +37,13 @@ describe('# Reply Model', () => { it('called Reply.init with the correct parameters', () => { expect(Reply.init).to.have.been.calledWithMatch( { - comment: DataTypes.TEXT, - }, + comment: DataTypes.TEXT + } ) }) }) - // 檢查 reply 的關聯是否正確 + // 檢查 reply 的關聯是否正確 context('associations', () => { const User = 'User' const Tweet = 'Tweet' @@ -53,12 +53,12 @@ describe('# Reply Model', () => { Reply.associate({ Tweet }) }) - it('should belong to user', (done) => { + it('should belong to user', done => { // 檢查是否有呼叫 belongsTo(User) expect(Reply.belongsTo).to.have.been.calledWith(User) done() }) - it('should belong to tweet', (done) => { + it('should belong to tweet', done => { // 檢查是否有呼叫 belongsTo(Tweet) expect(Reply.belongsTo).to.have.been.calledWith(Tweet) done() @@ -66,40 +66,38 @@ describe('# Reply Model', () => { }) // 檢查 model 的新增、修改、刪除、更新 context('action', () => { - let data = null // 檢查 db.Reply 是否真的可以新增一筆資料 - it('create', (done) => { - db.Reply.create({}).then((reply) => { + it('create', done => { + db.Reply.create({}).then(reply => { data = reply done() }) }) // 檢查 db.Reply 是否真的可以讀取一筆資料 - it('read', (done) => { - db.Reply.findByPk(data.id).then((reply) => { + it('read', done => { + db.Reply.findByPk(data.id).then(reply => { expect(data.id).to.be.equal(reply.id) - done() - }) + done() + }) }) // 檢查 db.Reply 是否真的可以更新一筆資料 - it('update', (done) => { - db.Reply.update({}, { where: { id: data.id }}).then(() => { - db.Reply.findByPk(data.id).then((reply) => { - expect(data.updatedAt).to.be.not.equal(reply.updatedAt) + it('update', done => { + db.Reply.update({}, { where: { id: data.id } }).then(() => { + db.Reply.findByPk(data.id).then(reply => { + expect(data.updatedAt).to.be.not.equal(reply.updatedAt) done() }) }) }) // 檢查 db.Reply 是否真的可以刪除一筆資料 - it('delete', (done) => { - db.Reply.destroy({ where: { id: data.id }}).then(() => { - db.Reply.findByPk(data.id).then((reply) => { - expect(reply).to.be.equal(null) + it('delete', done => { + db.Reply.destroy({ where: { id: data.id } }).then(() => { + db.Reply.findByPk(data.id).then(reply => { + expect(reply).to.be.equal(null) done() }) }) }) }) - }) diff --git a/test/models/Tweet.spec.js b/test/models/Tweet.spec.js index 5335b84bdd..fbec60f20f 100644 --- a/test/models/Tweet.spec.js +++ b/test/models/Tweet.spec.js @@ -1,7 +1,7 @@ -const chai = require('chai'); -const sinon = require('sinon'); -const proxyquire = require('proxyquire'); -chai.use(require('sinon-chai')); +const chai = require('chai') +const sinon = require('sinon') +const proxyquire = require('proxyquire') +chai.use(require('sinon-chai')) const { expect } = require('chai') const { @@ -37,8 +37,8 @@ describe('# Tweet Model', () => { it('called Tweet.init with the correct parameters', () => { expect(Tweet.init).to.have.been.calledWithMatch( { - description: DataTypes.TEXT, - }, + description: DataTypes.TEXT + } ) }) }) @@ -55,17 +55,17 @@ describe('# Tweet Model', () => { Tweet.associate({ User }) }) - it('should have many replies', (done) => { + it('should have many replies', done => { // 檢查是否有呼叫 hasMany(Reply) expect(Tweet.hasMany).to.have.been.calledWith(Reply) done() }) - it('should have many likes', (done) => { + it('should have many likes', done => { // 檢查是否有呼叫 hasMany(Like) expect(Tweet.hasMany).to.have.been.calledWith(Like) done() }) - it('should belong to user', (done) => { + it('should belong to user', done => { // 檢查是否有呼叫 belongsTo(User) expect(Tweet.belongsTo).to.have.been.calledWith(User) done() @@ -74,40 +74,38 @@ describe('# Tweet Model', () => { // // 檢查 model 的新增、修改、刪除、更新 context('action', () => { - let data = null // 檢查 db.Tweet 是否真的可以新增一筆資料 - it('create', (done) => { - db.Tweet.create({UserId: 1, description: 'hi'}).then((tweet) => { + it('create', done => { + db.Tweet.create({ UserId: 1, description: 'hi' }).then(tweet => { data = tweet done() }) }) // 檢查 db.Tweet 是否真的可以讀取一筆資料 - it('read', (done) => { - db.Tweet.findByPk(data.id).then((tweet) => { + it('read', done => { + db.Tweet.findByPk(data.id).then(tweet => { expect(data.id).to.be.equal(tweet.id) - done() - }) + done() + }) }) // 檢查 db.Tweet 是否真的可以更新一筆資料 - it('update', (done) => { - db.Tweet.update({}, { where: { id: data.id }}).then(() => { - db.Tweet.findByPk(data.id).then((tweet) => { - expect(data.updatedAt).to.be.not.equal(tweet.updatedAt) + it('update', done => { + db.Tweet.update({}, { where: { id: data.id } }).then(() => { + db.Tweet.findByPk(data.id).then(tweet => { + expect(data.updatedAt).to.be.not.equal(tweet.updatedAt) done() }) }) }) // 檢查 db.Tweet 是否真的可以刪除一筆資料 - it('delete', (done) => { - db.Tweet.destroy({ where: { id: data.id }}).then(() => { - db.Tweet.findByPk(data.id).then((tweet) => { - expect(tweet).to.be.equal(null) + it('delete', done => { + db.Tweet.destroy({ where: { id: data.id } }).then(() => { + db.Tweet.findByPk(data.id).then(tweet => { + expect(tweet).to.be.equal(null) done() }) }) }) }) - }) diff --git a/test/models/User.spec.js b/test/models/User.spec.js index 0bb4c2dad7..a6a4aa12ec 100644 --- a/test/models/User.spec.js +++ b/test/models/User.spec.js @@ -1,6 +1,6 @@ const chai = require('chai') const sinon = require('sinon') -const proxyquire = require('proxyquire'); +const proxyquire = require('proxyquire') chai.use(require('sinon-chai')) const { expect } = require('chai') @@ -37,7 +37,7 @@ describe('# User Model', () => { it('called User.init with the correct parameters', () => { expect(User.init).to.have.been.calledWithMatch( { - name: DataTypes.STRING, + name: DataTypes.STRING } ) }) @@ -56,22 +56,22 @@ describe('# User Model', () => { User.associate({ User }) }) - it('should have many replies', (done) => { + it('should have many replies', done => { // 檢查是否有呼叫 hasMany(Reply) expect(User.hasMany).to.have.been.calledWith(Reply) done() }) - it('should have many tweets', (done) => { + it('should have many tweets', done => { // 檢查是否有呼叫 hasMany(Tweet) expect(User.hasMany).to.have.been.calledWith(Tweet) done() }) - it('should have many likes', (done) => { + it('should have many likes', done => { // 檢查是否有呼叫 hasMany(Like) expect(User.hasMany).to.have.been.calledWith(Like) done() }) - it('should have many Users', (done) => { + it('should have many Users', done => { // 檢查是否有呼叫 belongsToMany(User) expect(User.belongsToMany).to.have.been.calledWith(User) done() @@ -82,32 +82,32 @@ describe('# User Model', () => { context('action', () => { let data = null // 檢查 db.User 是否真的可以新增一筆資料 - it('create', (done) => { - db.User.create({}).then((user) => { + it('create', done => { + db.User.create({}).then(user => { data = user done() }) }) // 檢查 db.User 是否真的可以讀取一筆資料 - it('read', (done) => { - db.User.findByPk(data.id).then((user) => { + it('read', done => { + db.User.findByPk(data.id).then(user => { expect(data.id).to.be.equal(user.id) done() }) }) // 檢查 db.User 是否真的可以更新一筆資料 - it('update', (done) => { + it('update', done => { db.User.update({}, { where: { id: data.id } }).then(() => { - db.User.findByPk(data.id).then((user) => { + db.User.findByPk(data.id).then(user => { expect(data.updatedAt).to.be.not.equal(user.updatedAt) done() }) }) }) // 檢查 db.User 是否真的可以刪除一筆資料 - it('delete', (done) => { + it('delete', done => { db.User.destroy({ where: { id: data.id } }).then(() => { - db.User.findByPk(data.id).then((user) => { + db.User.findByPk(data.id).then(user => { expect(user).to.be.equal(null) done() }) diff --git a/test/requests/admin.spec.js b/test/requests/admin.spec.js index a8006197f7..01b1eb17fa 100644 --- a/test/requests/admin.spec.js +++ b/test/requests/admin.spec.js @@ -2,119 +2,110 @@ const chai = require('chai') const request = require('supertest') const sinon = require('sinon') const app = require('../../app') -const helpers = require('../../_helpers'); -const should = chai.should(); -const expect = chai.expect; +const helpers = require('../../_helpers') +const should = chai.should() +const expect = chai.expect const db = require('../../models') const passport = require('../../config/passport') // admin 相關功能測試 // 1. 管理者可以看見站內所有的使用者 -// 2. 管理者可以刪除使用者的推文 +// 2. 管理者可以刪除使用者的推文 describe('# admin requests', () => { - context('# GET ', () => { - describe(' /api/admin/users', () => { - before(async() => { + before(async () => { // 清除 User table 的測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'admin'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'admin' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) }) // GET /admin/users - 看見站內所有的使用者 - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .get('/api/admin/users') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查回傳資料是否是陣列類型 - expect(res.body).to.be.an('array'); + expect(res.body).to.be.an('array') // 檢查回傳資料是否有 3 筆使用者資料 - res.body.length.should.equal(3); - return done(); + res.body.length.should.equal(3) + return done() }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); + }) + }) context('# DELETE ', () => { - describe(' /api/admin/tweets/:id', () => { - before(async() => { + before(async () => { // 清除 User, Tweet table 的測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'admin'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'admin' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Tweet.create({UserId: 1, description: 'User1 的 description'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Tweet.create({ UserId: 1, description: 'User1 的 description' }) }) // DELETE /admin/tweets/:id - 刪除使用者的推文 - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .delete('/api/admin/tweets/1') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查是否 Tweet table 中的資料是空的,表示有刪除成功 db.Tweet.findByPk(1).then(tweet => { expect(tweet).to.be.null - return done(); + return done() }) - }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); - -}); + }) + }) +}) diff --git a/test/requests/followship.spec.js b/test/requests/followship.spec.js index 45c90131bb..a96fc3122d 100644 --- a/test/requests/followship.spec.js +++ b/test/requests/followship.spec.js @@ -2,9 +2,9 @@ const chai = require('chai') const request = require('supertest') const sinon = require('sinon') const app = require('../../app') -const helpers = require('../../_helpers'); +const helpers = require('../../_helpers') const should = chai.should() -const expect = chai.expect; +const expect = chai.expect const db = require('../../models') const passport = require('../../config/passport') @@ -12,112 +12,104 @@ const passport = require('../../config/passport') // 1. 可以追蹤使用者 // 2. 可以刪除追蹤使用者 describe('# followship requests', () => { - context('# POST ', () => { - describe(' /api/followships', () => { - before(async() => { + before(async () => { // 清除 User, Followship table 的測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) }) // 新增 POST /followships - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .post('/api/followships') .send('id=2') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查 Followship 資料裡,是否有 followerId=1, followingId = 2 的資料 db.Followship.findByPk(1).then(followship => { - followship.followerId.should.equal(1); - followship.followingId.should.equal(2); - return done(); + followship.followerId.should.equal(1) + followship.followingId.should.equal(2) + return done() }) }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); + }) + }) context('# DELETE ', () => { - describe(' /api/followships/:followingId', () => { - before(async() => { + before(async () => { // 清除 User table 的測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Followship.create({followerId: 1, followingId: 2}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Followship.create({ followerId: 1, followingId: 2 }) }) // 刪除 DETELE /followships/:followingId - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .delete('/api/followships/2') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查 Followship 的資料是否已空,表示已被刪除 db.Followship.findByPk(1).then(followship => { expect(followship).to.be.null - return done(); + return done() }) }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); - -}); + }) + }) +}) diff --git a/test/requests/like.spec.js b/test/requests/like.spec.js index 3f3b957c8e..1864b99563 100644 --- a/test/requests/like.spec.js +++ b/test/requests/like.spec.js @@ -2,120 +2,114 @@ const chai = require('chai') const request = require('supertest') const sinon = require('sinon') const app = require('../../app') -const helpers = require('../../_helpers'); -const should = chai.should(); -const expect = chai.expect; +const helpers = require('../../_helpers') +const should = chai.should() +const expect = chai.expect const db = require('../../models') const passport = require('../../config/passport') describe('# like requests', () => { - context('# POST ', () => { - describe(' /api/tweets/:id/like', () => { - before(async() => { + before(async () => { // 清除 User, Tweet, Like table 的測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Like.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Like.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet1'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet1' }) }) // POST /tweets/:id/like 喜歡一則推文 - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .post('/api/tweets/1/like') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查 Like 資料裡,是否有 UserId=1, TweetId =1 的資料 db.Like.findByPk(1).then(like => { - like.UserId.should.equal(1); - like.TweetId.should.equal(1); - return done(); + like.UserId.should.equal(1) + like.TweetId.should.equal(1) + return done() }) }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Like.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Like.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); + }) describe(' /api/tweets/:id/unlike', () => { - before(async() => { + before(async () => { // 清除 User, Tweet, Like table 的測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Like.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Like.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet1'}) - await db.Like.create({UserId: 1, TweetId: 1}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet1' }) + await db.Like.create({ UserId: 1, TweetId: 1 }) }) // POST /tweets/:id/unlike 取消喜歡 - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .post('/api/tweets/1/unlike') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查是否 Like table 中的資料是空的,表示有刪除成功 db.Like.findByPk(1).then(like => { expect(like).to.be.null - return done(); + return done() }) }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Like.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Like.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); - -}); + }) + }) +}) diff --git a/test/requests/reply.spec.js b/test/requests/reply.spec.js index c355eb7eee..d221e9099b 100644 --- a/test/requests/reply.spec.js +++ b/test/requests/reply.spec.js @@ -2,124 +2,116 @@ const chai = require('chai') const request = require('supertest') const sinon = require('sinon') const app = require('../../app') -const helpers = require('../../_helpers'); -const should = chai.should(); -const expect = chai.expect; +const helpers = require('../../_helpers') +const should = chai.should() +const expect = chai.expect const db = require('../../models') const passport = require('../../config/passport') describe('# reply requests', () => { - context('# POST ', () => { - describe(' /api/tweets/:tweet_id/replies', () => { - before(async() => { + before(async () => { // 清除 User, Tweet, Reply table 的測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Reply.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Reply.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet1'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet1' }) }) // 新增回覆 POST /tweets/:tweet_id/replies - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .post('/api/tweets/1/replies') .send('comment=comment') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查是否有成功新增留言 db.Reply.findByPk(1).then(reply => { - reply.comment.should.equal('comment'); - reply.UserId.should.equal(1); - reply.TweetId.should.equal(1); - return done(); + reply.comment.should.equal('comment') + reply.UserId.should.equal(1) + reply.TweetId.should.equal(1) + return done() }) }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Reply.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Reply.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); + }) + }) context('# GET ', () => { - describe('GET /api/tweets/:tweet_id/replies', () => { - before(async() => { + before(async () => { // 清除 User table 的測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Reply.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Reply.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'}) - await db.Reply.create({UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' }) + await db.Reply.create({ UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment' }) }) // 瀏覽 GET /tweets/:tweet_id/replies - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .get('/api/tweets/1/replies') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查是否有成功取得留言 - expect(res.body).to.be.an('array'); - res.body[0].comment.should.equal('Tweet1 的 comment'); - return done(); + expect(res.body).to.be.an('array') + res.body[0].comment.should.equal('Tweet1 的 comment') + return done() }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Reply.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Reply.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); - -}); + }) + }) +}) diff --git a/test/requests/tweet.spec.js b/test/requests/tweet.spec.js index 1976d7d5b9..bf03fc8bbf 100644 --- a/test/requests/tweet.spec.js +++ b/test/requests/tweet.spec.js @@ -2,130 +2,122 @@ const chai = require('chai') const request = require('supertest') const sinon = require('sinon') const app = require('../../app') -const helpers = require('../../_helpers'); -const should = chai.should(); -const expect = chai.expect; +const helpers = require('../../_helpers') +const should = chai.should() +const expect = chai.expect const db = require('../../models') const passport = require('../../config/passport') describe('# tweet requests', () => { - context('# POST ', () => { - describe('POST /api/tweets', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) }) // 新增推文 - POST /tweets - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .post('/api/tweets') .send('description=description') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查是否有回傳正確資料 db.Tweet.findByPk(1).then(tweet => { - tweet.description.should.equal('description'); - tweet.UserId.should.equal(1); - return done(); + tweet.description.should.equal('description') + tweet.UserId.should.equal(1) + return done() }) }) - }); + }) after(async () => { - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); + }) + }) context('# GET ', () => { - describe('GET /api/tweets', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'}) - await db.Reply.create({UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' }) + await db.Reply.create({ UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment' }) }) // GET /tweets - 所有推文,包括推文作者 - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .get('/api/tweets') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); - expect(res.body).to.be.an('array'); + .end(function (err, res) { + if (err) return done(err) + expect(res.body).to.be.an('array') // 檢查是否回傳資料有 User1 的 Tweet1 - res.body[0].description.should.equal('User1 的 Tweet1'); - return done(); + res.body[0].description.should.equal('User1 的 Tweet1') + return done() }) - }); + }) // GET /tweets/:tweet_id - 一筆推文 - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .get('/api/tweets/1') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); - expect(res.body).to.be.an('object'); - // 檢查是否回傳資料有 User1 的 Tweet1 - res.body.description.should.equal('User1 的 Tweet1'); - return done(); + .end(function (err, res) { + if (err) return done(err) + expect(res.body).to.be.an('object') + // 檢查是否回傳資料有 User1 的 Tweet1 + res.body.description.should.equal('User1 的 Tweet1') + return done() }) - }); + }) after(async () => { - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); - -}); + }) + }) +}) diff --git a/test/requests/user.spec.js b/test/requests/user.spec.js index e19d5e4229..bc27fc0380 100644 --- a/test/requests/user.spec.js +++ b/test/requests/user.spec.js @@ -2,413 +2,391 @@ const chai = require('chai') const request = require('supertest') const sinon = require('sinon') const app = require('../../app') -const helpers = require('../../_helpers'); +const helpers = require('../../_helpers') const should = chai.should() -const expect = chai.expect; +const expect = chai.expect const db = require('../../models') const passport = require('../../config/passport') describe('# user requests', () => { - context('# POST ', () => { - describe('POST /api/users', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) // 註冊自己的帳號 POST /users - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .post('/api/users') .send('account=User1&name=User1&email=User1@example.com&password=User1&checkPassword=User1') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查是否有成功新增資料到資料庫裡 db.User.findByPk(1).then(user => { - user.account.should.equal('User1'); - user.email.should.equal('User1@example.com'); - return done(); + user.account.should.equal('User1') + user.email.should.equal('User1@example.com') + return done() }) }) - }); + }) after(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); - + }) + }) context('# GET ', () => { - describe('GET /users/:id', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) }) - // GET /users/:id - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .get('/api/users/1') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查是否回傳資料裡有 root 的資料 - res.body.name.should.equal('root'); + res.body.name.should.equal('root') - return done(); + return done() }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - + }) describe('GET /users/:id/tweets', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' }) }) // GET /users/:id/tweets - 看見某使用者發過的推文 - it(' - self successfully', (done) => { + it(' - self successfully', done => { request(app) .get('/api/users/1/tweets') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) - expect(res.body).to.be.an('array'); + expect(res.body).to.be.an('array') // 有回傳某使用者的推文資料 - res.body[0].description.should.equal('User1 的 Tweet1'); + res.body[0].description.should.equal('User1 的 Tweet1') - return done(); + return done() }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); + }) describe('GET /users/:id/replied_tweets', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Reply.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Reply.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'}) - await db.Reply.create({UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' }) + await db.Reply.create({ UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment' }) }) // GET /users/:id/replied_tweets - 看見某使用者發過回覆的推文 - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .get('/api/users/1/replied_tweets') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) - expect(res.body).to.be.an('array'); + expect(res.body).to.be.an('array') // 有回傳 Tweet1 的 comment 這筆資料 - res.body[0].comment.should.equal('Tweet1 的 comment'); + res.body[0].comment.should.equal('Tweet1 的 comment') - return done(); + return done() }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Reply.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Reply.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); + }) describe('GET /users/:id/likes', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Like.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Like.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet1'}) - await db.Like.create({UserId: 1, TweetId: 1}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet1' }) + await db.Like.create({ UserId: 1, TweetId: 1 }) }) - // GET /users/:id/likes - 看見某使用者點過的 Like - it(' - successfully', (done) => { + // GET /users/:id/likes - 看見某使用者點過的 Like + it(' - successfully', done => { request(app) .get('/api/users/1/likes') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); - expect(res.body).to.be.an('array'); + .end(function (err, res) { + if (err) return done(err) + expect(res.body).to.be.an('array') // 檢查回傳資料是否有 TweetId = 1 - res.body[0].TweetId.should.equal(1); + res.body[0].TweetId.should.equal(1) - return done(); + return done() }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Like.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Like.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - + }) describe('GET /users/:id/followings', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Followship.create({followerId: 1, followingId: 2}) + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Followship.create({ followerId: 1, followingId: 2 }) }) // GET /users/:id/followings - 看見某使用者跟隨中的人 - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .get('/api/users/1/followings') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) - expect(res.body).to.be.an('array'); - //回傳資料中是否有跟隨中的人的 id = 2 - res.body[0].followingId.should.equal(2); + expect(res.body).to.be.an('array') + // 回傳資料中是否有跟隨中的人的 id = 2 + res.body[0].followingId.should.equal(2) - return done(); + return done() }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); + }) describe('GET /users/:id/followers', () => { - before(async() => { + before(async () => { // 清除測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'}) - await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'}) - await db.Followship.create({followerId: 1, followingId: 2}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' }) + await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' }) + await db.Followship.create({ followerId: 1, followingId: 2 }) }) // GET /users/:id/followers - 看見某使用者的跟隨者 - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .get('/api/users/2/followers') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) - expect(res.body).to.be.an('array'); + expect(res.body).to.be.an('array') // 有跟隨者的 followerId = 1 - res.body[0].followerId.should.equal(1); + res.body[0].followerId.should.equal(1) - return done(); + return done() }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.Tweet.destroy({where: {},truncate: true, force: true}) - await db.Followship.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.Tweet.destroy({ where: {}, truncate: true, force: true }) + await db.Followship.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - - }); - + }) + }) context('# PUT ', () => { - describe('PUT /api/users/:id', () => { - before(async() => { + before(async () => { // 清除 User, Tweet table 的測試資料庫資料 - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) // 模擬登入資料 - const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => { - callback(null, {...rootUser}, null); - return (req,res,next)=>{}; - }); + const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => { + callback(null, { ...rootUser }, null) + return (req, res, next) => {} + }) this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + helpers, 'getUser' + ).returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1', introduction: 'User1'}) + await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1', introduction: 'User1' }) }) // 編輯自己所有的資料 PUT /users/:id - it(' - successfully', (done) => { + it(' - successfully', done => { request(app) .put('/api/users/1') .send('name=User11&introduction=User11') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) db.User.findByPk(1).then(user => { // 檢查資料是否有變更 - user.name.should.equal('User11'); - user.introduction.should.equal('User11'); - return done(); + user.name.should.equal('User11') + user.introduction.should.equal('User11') + return done() }) }) - }); + }) after(async () => { // 清除登入及測試資料庫資料 - this.authenticate.restore(); - this.getUser.restore(); - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }); - await db.User.destroy({where: {},truncate: true, force: true}) - await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }); + this.authenticate.restore() + this.getUser.restore() + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true }) + await db.User.destroy({ where: {}, truncate: true, force: true }) + await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true }) }) - - }); - - }); - -}); \ No newline at end of file + }) + }) +}) From c8531cc3bf32c12e7798f5a69e4679bbe4474618 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 21 Aug 2023 18:42:26 +0800 Subject: [PATCH 007/170] feat: adminController add 3 routes --- app.js | 10 ++ controllers/apis/admin-controller.js | 114 +++++--------------- controllers/apis/user-controller.js | 1 + package-lock.json | 112 +++++++++---------- package.json | 5 +- routes/modules/admin.js | 3 + seeders/20230821081029-replies-seed-file.js | 36 +++---- 7 files changed, 119 insertions(+), 162 deletions(-) diff --git a/app.js b/app.js index b27cc6744a..f71436075d 100644 --- a/app.js +++ b/app.js @@ -1,9 +1,19 @@ const express = require('express') const helpers = require('./_helpers') +const bodyParser = require('body-parser') +const session = require('express-session') const app = express() + +if (process.NODE_ENV !== 'production') { + require('dotenv').config() +} const port = 3000 +// bodyparser設定 +app.use(bodyParser.urlencoded({ extended: true })) +app.use(bodyParser.json()) + // use helpers.getUser(req) to replace req.user function authenticated (req, res, next) { // passport.authenticate('jwt', { ses... diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 8038b06510..4b21e1c607 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -2,21 +2,17 @@ const db = require('../../models') const { User, Tweet, Reply, Like } = db const bcrypt = require('bcrypt-nodejs') const jwt = require('jsonwebtoken') -const defaultLimit = 10 const adminController = { + // Admin 取得所有使用者 getUsers: (req, res) => { const options = { - limit: +req.query.limit || defaultLimit, - offset: +req.query.offset || 0, raw: true, - order: [['tweetNum', 'desc']], attributes: { exclude: [ 'email', 'introduction', 'password', - 'lastLoginAt', 'updatedAt', 'createdAt' ] @@ -39,12 +35,10 @@ const adminController = { }) }) }, + // Admin取得所有貼文 getTweets: (req, res) => { const options = { - limit: +req.query.limit || defaultLimit, - offset: +req.query.offset || 0, - attributes: ['id', 'description', 'likeNum', 'replyNum', 'createdAt'], - order: [['createdAt', 'desc']], + attributes: ['id', 'description', 'createdAt'], include: [ { model: User, @@ -63,94 +57,40 @@ const adminController = { .catch(() => res.status(500).json({ status: 'error', - message: error + message: 'error' }) ) }, - deleteTweet: (req, res) => { - const options = { - include: [ - { model: Reply, attributes: ['id'], raw: true }, - { model: Like, attributes: ['id', 'UserId'] } - ] - } - Tweet.findByPk(+req.params.tweetId, options) - .then(async tweet => { - await tweet.destroy() - await User.decrement({ tweetNum: 1 }, { where: { id: tweet.UserId } }) - if (tweet.Replies.length) { - await Reply.destroy({ - where: { id: tweet.Replies.map(reply => reply.id) } - }) - } - if (tweet.Likes.length) { - await Like.destroy({ - where: { id: tweet.Likes.map(like => like.id) } - }) - await User.decrement( - { likeNum: 1 }, - { where: { id: tweet.Likes.map(like => like.UserId) } } + // Admin刪除一篇貼文 + deleteTweet: (req, cb) => { + return Promise.all([ + Tweet.destroy({ + where: { id: req.params.id }, + raw: true, + nest: true + }), + Like.destroy({ + where: { TweetId: req.params.id }, + raw: true, + nest: true + }) + ]) + .then(tweet => { + if (!tweet) { + throw new Error( + '此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除' ) } - res.status(200).json({ + return cb(null, { status: 'success', - message: 'Successfully delete tweet.' + message: '刪除貼文成功' }) }) - .catch(error => - res.status(500).json({ - status: 'error', - message: error - }) - ) + .catch(err => cb(err)) }, + // Admin 登入 login: (req, res) => { - const { password, email } = req.body - if (!password || !email) { - return res.status(400).json({ - status: 'error', - message: 'Password or email can not be empty.' - }) - } - - User.findOne({ where: { email, role: 'admin' } }) - .then(user => { - if (!user) { - return res.status(401).json({ - status: 'error', - message: "This admin account doesn't exist." - }) - } - if (!bcrypt.compareSync(password, user.password)) { - return res.status(401).json({ - status: 'error', - message: 'Password incorrect.' - }) - } - - const payload = { - id: user.id - } - const token = jwt.sign(payload, 'numberFive') - return res.status(200).json({ - status: 'success', - message: 'Administrator successfully login.', - token, - User: { - id: user.id, - name: user.name, - account: user.account, - email: user.email, - role: user.role - } - }) - }) - .catch(error => - res.status(500).json({ - status: 'error', - message: error - }) - ) + // 未完成 } } diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index a153a32c2c..bdab224d98 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -3,6 +3,7 @@ const db = require('../models') const { User } = db const userController = { signUp: (req, res) => { + // 待完成 bcrypt .hash(req.body.password, 10) .then(hash => diff --git a/package-lock.json b/package-lock.json index f33df23f6d..ccddc7943d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,11 +12,12 @@ "bcrypt": "^5.1.1", "bcrypt-nodejs": "0.0.3", "bcryptjs": "^2.4.3", - "body-parser": "^1.18.3", + "body-parser": "^1.20.2", "chai": "^4.2.0", "connect-flash": "^0.1.1", + "dotenv": "^16.3.1", "express": "^4.16.4", - "express-session": "^1.15.6", + "express-session": "^1.17.3", "faker": "^5.5.3", "method-override": "^3.0.0", "mocha": "^6.0.2", @@ -692,20 +693,20 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", + "qs": "6.11.0", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -984,9 +985,9 @@ } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "engines": { "node": ">= 0.6" } @@ -1169,6 +1170,17 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", @@ -2279,11 +2291,11 @@ } }, "node_modules/express-session": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", - "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", "dependencies": { - "cookie": "0.4.1", + "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~2.0.0", @@ -2296,14 +2308,6 @@ "node": ">= 0.8.0" } }, - "node_modules/express-session/node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/express/node_modules/body-parser": { "version": "1.19.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", @@ -4515,9 +4519,9 @@ } }, "node_modules/qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "dependencies": { "side-channel": "^1.0.4" }, @@ -4565,9 +4569,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -6530,20 +6534,20 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "requires": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", + "qs": "6.11.0", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" } @@ -6770,9 +6774,9 @@ } }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "cookie": { "version": "0.4.2", @@ -6908,6 +6912,11 @@ "esutils": "^2.0.2" } }, + "dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" + }, "dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", @@ -7793,11 +7802,11 @@ } }, "express-session": { - "version": "1.17.2", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", - "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", "requires": { - "cookie": "0.4.1", + "cookie": "0.4.2", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~2.0.0", @@ -7805,13 +7814,6 @@ "parseurl": "~1.3.3", "safe-buffer": "5.2.1", "uid-safe": "~2.1.5" - }, - "dependencies": { - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - } } }, "ext": { @@ -9427,9 +9429,9 @@ "dev": true }, "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", "requires": { "side-channel": "^1.0.4" } @@ -9451,9 +9453,9 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "requires": { "bytes": "3.1.2", "http-errors": "2.0.0", diff --git a/package.json b/package.json index 9479bb34e3..e26b3f1c3d 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,12 @@ "bcrypt": "^5.1.1", "bcrypt-nodejs": "0.0.3", "bcryptjs": "^2.4.3", - "body-parser": "^1.18.3", + "body-parser": "^1.20.2", "chai": "^4.2.0", "connect-flash": "^0.1.1", + "dotenv": "^16.3.1", "express": "^4.16.4", - "express-session": "^1.15.6", + "express-session": "^1.17.3", "faker": "^5.5.3", "method-override": "^3.0.0", "mocha": "^6.0.2", diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 56b56d14f6..a0c545466c 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -1,9 +1,12 @@ const express = require('express') const router = express.Router() const adminController = require('../../controllers/admin-controller') + router.post('/signIn', adminController.signIn) router.get('/users', adminController.getUsers) router.delete('/tweets/:id', adminController.deleteTweet) router.get('/tweets', adminController.getTweets) + router.use('/', (req, res) => res.redirect('api/admin/users')) + module.exports = router diff --git a/seeders/20230821081029-replies-seed-file.js b/seeders/20230821081029-replies-seed-file.js index 198aa6224c..e5fd76191a 100644 --- a/seeders/20230821081029-replies-seed-file.js +++ b/seeders/20230821081029-replies-seed-file.js @@ -1,39 +1,39 @@ -"use strict"; -const faker = require("faker"); -const db = require("../models"); -const User = db.User; -const Tweet = db.Tweet; +'use strict' +const faker = require('faker') +const db = require('../models') +const User = db.User +const Tweet = db.Tweet module.exports = { up: async (queryInterface, Sequelize) => { const userData = await User.findAll({ raw: true, nest: true, - where: { role: "user" }, - attributes: ["id"], - }); + where: { role: 'user' }, + attributes: ['id'] + }) const tweetData = await Tweet.findAll({ raw: true, nest: true, - attributes: ["id"], - }); + attributes: ['id'] + }) await queryInterface.bulkInsert( - "Replies", + 'Replies', Array.from({ length: 150 }).map((d, i) => { const tweet = { TweetId: tweetData[Math.floor(i / 3)].id, UserId: userData[Math.floor(Math.random() * userData.length)].id, comment: faker.lorem.text(), createdAt: new Date(), - updatedAt: new Date(), - }; - return tweet; + updatedAt: new Date() + } + return tweet }), {} - ); + ) }, down: async (queryInterface, Sequelize) => { - return queryInterface.bulkDelete("Replies", null, {}); - }, -}; + return queryInterface.bulkDelete('Replies', null, {}) + } +} From 0c4baea2136cc02bcb0935bb7f04bf4343e89298 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Mon, 21 Aug 2023 21:43:30 +0800 Subject: [PATCH 008/170] feat: add error-handler --- app.js | 6 +++++- middleware/error-handler.js | 16 ++++++++++++++++ package-lock.json | 19 +++++++++++++++++++ package.json | 1 + routes/index.js | 8 ++++++++ services/admin-services.js | 0 services/followship-services.js | 0 services/reply-services.js | 0 services/tweet-services.js | 0 services/user-services.js | 0 10 files changed, 49 insertions(+), 1 deletion(-) delete mode 100644 services/admin-services.js delete mode 100644 services/followship-services.js delete mode 100644 services/reply-services.js delete mode 100644 services/tweet-services.js delete mode 100644 services/user-services.js diff --git a/app.js b/app.js index b27cc6744a..296e9e3975 100644 --- a/app.js +++ b/app.js @@ -1,8 +1,12 @@ +if (process.env.NODE_ENV !== 'production') { + require('dotenv').config() +} + const express = require('express') const helpers = require('./_helpers') const app = express() -const port = 3000 +const port = process.env.PORT || 3000 // use helpers.getUser(req) to replace req.user function authenticated (req, res, next) { diff --git a/middleware/error-handler.js b/middleware/error-handler.js index e69de29bb2..360dbdf84f 100644 --- a/middleware/error-handler.js +++ b/middleware/error-handler.js @@ -0,0 +1,16 @@ +module.exports = { + apiErrorHandler (err, req, res, next) { + if (err instanceof Error) { + res.status(err.status || 500).json({ + status: 'error', + message: `${err.name}: ${err.message}` + }) + } else { + res.status(500).json({ + status: 'error', + message: `${err}` + }) + } + next(err) + } +} diff --git a/package-lock.json b/package-lock.json index ac576c6e54..19b918e108 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,6 +27,7 @@ "sinon-chai": "^3.3.0" }, "devDependencies": { + "dotenv": "^16.3.1", "eslint-config-standard": "^17.1.0", "proxyquire": "^2.1.3", "sequelize-test-helpers": "^1.4.2", @@ -1020,6 +1021,18 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", @@ -6387,6 +6400,12 @@ "esutils": "^2.0.2" } }, + "dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "dev": true + }, "dottie": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", diff --git a/package.json b/package.json index d2759c1bdf..16759c2630 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "sinon-chai": "^3.3.0" }, "devDependencies": { + "dotenv": "^16.3.1", "eslint-config-standard": "^17.1.0", "proxyquire": "^2.1.3", "sequelize-test-helpers": "^1.4.2", diff --git a/routes/index.js b/routes/index.js index e69de29bb2..cb1c51f4d7 100644 --- a/routes/index.js +++ b/routes/index.js @@ -0,0 +1,8 @@ +const express = require('express') +const router = express.Router() + +const { apiErrorHandler } = require('../../middleware/error-handler') + +router.use('/', apiErrorHandler) + +module.exports = router diff --git a/services/admin-services.js b/services/admin-services.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/followship-services.js b/services/followship-services.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/reply-services.js b/services/reply-services.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/tweet-services.js b/services/tweet-services.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/user-services.js b/services/user-services.js deleted file mode 100644 index e69de29bb2..0000000000 From 3277bd6d4db9f716b9dbc9d50addd75ef7f70062 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Mon, 21 Aug 2023 23:17:09 +0800 Subject: [PATCH 009/170] add getTweets and getTweet routes --- app.js | 4 ++++ controllers/apis/tweet-controller.js | 24 ++++++++++++++++++++++++ routes/index.js | 6 +++++- routes/modules/tweets.js | 9 +++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 routes/modules/tweets.js diff --git a/app.js b/app.js index 296e9e3975..5a488f0165 100644 --- a/app.js +++ b/app.js @@ -5,6 +5,8 @@ if (process.env.NODE_ENV !== 'production') { const express = require('express') const helpers = require('./_helpers') +const routes = require('./routes') + const app = express() const port = process.env.PORT || 3000 @@ -13,6 +15,8 @@ function authenticated (req, res, next) { // passport.authenticate('jwt', { ses... } +app.use(routes) + app.get('/', (req, res) => res.send('Hello World!')) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index e69de29bb2..82275ba3b5 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -0,0 +1,24 @@ +const { Tweet } = require('../../models') + +const tweetContorller = { + getTweets: (req, res, next) => { + return Tweet.findAll({ + raw: true + }) + .then(tweets => { + res.json(tweets) + }) + .catch(err => next(err)) + }, + getTweet: (req, res, next) => { + const TweetId = req.params.tweet_id + + return Tweet.findByPk(TweetId) + .then(tweet => { + res.json(tweet) + }) + .catch(err => next(err)) + } +} + +module.exports = tweetContorller diff --git a/routes/index.js b/routes/index.js index cb1c51f4d7..552697e345 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,7 +1,11 @@ const express = require('express') const router = express.Router() -const { apiErrorHandler } = require('../../middleware/error-handler') +const tweets = require('./modules/tweets') + +const { apiErrorHandler } = require('../middleware/error-handler') + +router.use('/api/tweets', tweets) router.use('/', apiErrorHandler) diff --git a/routes/modules/tweets.js b/routes/modules/tweets.js new file mode 100644 index 0000000000..3f51167c04 --- /dev/null +++ b/routes/modules/tweets.js @@ -0,0 +1,9 @@ +const express = require('express') +const router = express.Router() + +const tweetContorller = require('../../controllers/apis/tweet-controller') + +router.get('/:tweet_id', tweetContorller.getTweet) +router.get('/', tweetContorller.getTweets) + +module.exports = router From 20051c38d46d22c554930cccb271619f34c07118 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Mon, 21 Aug 2023 23:17:09 +0800 Subject: [PATCH 010/170] feat: add getTweets and getTweet routes --- app.js | 4 ++++ controllers/apis/tweet-controller.js | 24 ++++++++++++++++++++++++ routes/index.js | 6 +++++- routes/modules/tweets.js | 9 +++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 routes/modules/tweets.js diff --git a/app.js b/app.js index 296e9e3975..5a488f0165 100644 --- a/app.js +++ b/app.js @@ -5,6 +5,8 @@ if (process.env.NODE_ENV !== 'production') { const express = require('express') const helpers = require('./_helpers') +const routes = require('./routes') + const app = express() const port = process.env.PORT || 3000 @@ -13,6 +15,8 @@ function authenticated (req, res, next) { // passport.authenticate('jwt', { ses... } +app.use(routes) + app.get('/', (req, res) => res.send('Hello World!')) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index e69de29bb2..82275ba3b5 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -0,0 +1,24 @@ +const { Tweet } = require('../../models') + +const tweetContorller = { + getTweets: (req, res, next) => { + return Tweet.findAll({ + raw: true + }) + .then(tweets => { + res.json(tweets) + }) + .catch(err => next(err)) + }, + getTweet: (req, res, next) => { + const TweetId = req.params.tweet_id + + return Tweet.findByPk(TweetId) + .then(tweet => { + res.json(tweet) + }) + .catch(err => next(err)) + } +} + +module.exports = tweetContorller diff --git a/routes/index.js b/routes/index.js index cb1c51f4d7..552697e345 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,7 +1,11 @@ const express = require('express') const router = express.Router() -const { apiErrorHandler } = require('../../middleware/error-handler') +const tweets = require('./modules/tweets') + +const { apiErrorHandler } = require('../middleware/error-handler') + +router.use('/api/tweets', tweets) router.use('/', apiErrorHandler) diff --git a/routes/modules/tweets.js b/routes/modules/tweets.js new file mode 100644 index 0000000000..3f51167c04 --- /dev/null +++ b/routes/modules/tweets.js @@ -0,0 +1,9 @@ +const express = require('express') +const router = express.Router() + +const tweetContorller = require('../../controllers/apis/tweet-controller') + +router.get('/:tweet_id', tweetContorller.getTweet) +router.get('/', tweetContorller.getTweets) + +module.exports = router From 84bf59cf0941d004b2e18047957c3cdfa1cfb096 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 21 Aug 2023 23:38:06 +0800 Subject: [PATCH 011/170] test2 --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 7dd4e1e446..2d7e7482b7 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,7 @@ if (process.env.NODE_ENV !== "production") { require("dotenv").config(); } - +const test2 = "test2"; const express = require("express"); const helpers = require("./_helpers"); From 1294a61ce300f7e94399734c2b38d38f7512cc26 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Tue, 22 Aug 2023 00:39:34 +0800 Subject: [PATCH 012/170] refactor: made a lot of changes --- controllers/apis/admin-controller.js | 5 ++--- controllers/apis/user-controller.js | 2 +- package-lock.json | 1 - routes/index.js | 17 ++++++++++------- routes/modules/admin.js | 4 ++-- routes/modules/tweets.js | 9 --------- seeders/20230821074916-tweets-seed-file.js | 7 ++++--- seeders/20230821081029-replies-seed-file.js | 8 ++++---- 8 files changed, 23 insertions(+), 30 deletions(-) delete mode 100644 routes/modules/tweets.js diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 4b21e1c607..9b317524f7 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -1,7 +1,6 @@ const db = require('../../models') -const { User, Tweet, Reply, Like } = db -const bcrypt = require('bcrypt-nodejs') -const jwt = require('jsonwebtoken') +const { User, Tweet, Like } = db +// const bcrypt = require('bcrypt-nodejs') const adminController = { // Admin 取得所有使用者 diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index bdab224d98..c5893a52a1 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,5 +1,5 @@ const bcrypt = require('bcryptjs') -const db = require('../models') +const db = require('../../models') const { User } = db const userController = { signUp: (req, res) => { diff --git a/package-lock.json b/package-lock.json index 602b320e0e..8c4686b9fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6919,7 +6919,6 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", "dev": true - }, "dottie": { "version": "2.0.2", diff --git a/routes/index.js b/routes/index.js index 782d3f219c..0b0501c263 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,25 +1,28 @@ const express = require('express') const router = express.Router() -const userController = require('../controllers/user-controller') + const admin = require('./modules/admin') -const tweets = require('./modules/tweets') -const { apiErrorHandler } = require('../middleware/error-handler') -router.use('/api/tweets', tweets) +const userController = require('../controllers/apis/user-controller') +const tweetContorller = require('../controllers/apis/tweet-controller') + +const { apiErrorHandler } = require('../middleware/error-handler') // api/admin router.use('/api/admin', admin) // api/users -router.get('/api/users', userController.getUsers) -router.get('/api/signup', userController.signUpPage) +// router.get('/api/users', userController.getUsers) +// router.get('/api/signup', userController.signUpPage) router.post('/api/signup', userController.signUp) // api/tweets +router.get('/api/tweets/:tweet_id', tweetContorller.getTweet) +router.get('/api/tweets', tweetContorller.getTweets) // router.get("/restaurants", restController.getRestaurants); // router.use("/", (req, res) => res.redirect("/restaurants")); -router.use('/api/tweets', tweets) router.use('/', apiErrorHandler) + module.exports = router diff --git a/routes/modules/admin.js b/routes/modules/admin.js index a0c545466c..77eb2b9dd1 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -1,8 +1,8 @@ const express = require('express') const router = express.Router() -const adminController = require('../../controllers/admin-controller') +const adminController = require('../../controllers/apis/admin-controller') -router.post('/signIn', adminController.signIn) +// router.post('/signIn', adminController.signIn) router.get('/users', adminController.getUsers) router.delete('/tweets/:id', adminController.deleteTweet) router.get('/tweets', adminController.getTweets) diff --git a/routes/modules/tweets.js b/routes/modules/tweets.js deleted file mode 100644 index 3f51167c04..0000000000 --- a/routes/modules/tweets.js +++ /dev/null @@ -1,9 +0,0 @@ -const express = require('express') -const router = express.Router() - -const tweetContorller = require('../../controllers/apis/tweet-controller') - -router.get('/:tweet_id', tweetContorller.getTweet) -router.get('/', tweetContorller.getTweets) - -module.exports = router diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index 96153a2138..d9a406a4a3 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -4,14 +4,15 @@ const faker = require('faker') module.exports = { up: async (queryInterface, Sequelize) => { const data = [] + // eslint-disable-next-line array-callback-return Array.from({ length: 5 }).map((user, i) => { for (let j = 0; j < 10; ++j) { data.push({ id: j * 10 + i + 1, description: faker.lorem.text(140), - createdAt: new Date(), - updatedAt: new Date(), - UserId: i + 1 + created_at: new Date(), + updated_at: new Date(), + User_id: i + 1 }) } }) diff --git a/seeders/20230821081029-replies-seed-file.js b/seeders/20230821081029-replies-seed-file.js index e5fd76191a..726069084c 100644 --- a/seeders/20230821081029-replies-seed-file.js +++ b/seeders/20230821081029-replies-seed-file.js @@ -21,11 +21,11 @@ module.exports = { 'Replies', Array.from({ length: 150 }).map((d, i) => { const tweet = { - TweetId: tweetData[Math.floor(i / 3)].id, - UserId: userData[Math.floor(Math.random() * userData.length)].id, + Tweet_id: tweetData[Math.floor(i / 3)].id, + User_id: userData[Math.floor(Math.random() * userData.length)].id, comment: faker.lorem.text(), - createdAt: new Date(), - updatedAt: new Date() + created_at: new Date(), + updated_at: new Date() } return tweet }), From a4f8f954488f0e011a9f7775523b21a189f0e4e6 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 22 Aug 2023 11:13:21 +0800 Subject: [PATCH 013/170] chore: add 50 seed user --- controllers/apis/admin-controller.js | 7 +- routes/modules/admin.js | 2 +- seeders/20230821044414-users-seed-file.js | 94 ++++++++++++----------- 3 files changed, 53 insertions(+), 50 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 9b317524f7..92afca18d9 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -46,7 +46,7 @@ const adminController = { } ] } - Tweet.findAll(options) + return Tweet.findAll(options) .then(tweets => { tweets.forEach(tweet => { tweet.description = tweet.description.substring(0, 50) @@ -56,7 +56,7 @@ const adminController = { .catch(() => res.status(500).json({ status: 'error', - message: 'error' + message: 'errorrr' }) ) }, @@ -88,8 +88,9 @@ const adminController = { .catch(err => cb(err)) }, // Admin 登入 - login: (req, res) => { + signIn: (req, res) => { // 未完成 + const { email, password } = req.body } } diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 77eb2b9dd1..41f40a4c60 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -2,7 +2,7 @@ const express = require('express') const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') -// router.post('/signIn', adminController.signIn) +router.post('/login', adminController.signIn) router.get('/users', adminController.getUsers) router.delete('/tweets/:id', adminController.deleteTweet) router.get('/tweets', adminController.getTweets) diff --git a/seeders/20230821044414-users-seed-file.js b/seeders/20230821044414-users-seed-file.js index 3364ace0b8..01d1ad5898 100644 --- a/seeders/20230821044414-users-seed-file.js +++ b/seeders/20230821044414-users-seed-file.js @@ -1,53 +1,55 @@ -'use strict' -const bcrypt = require('bcrypt') -const faker = require('faker') +"use strict"; +const bcrypt = require("bcrypt"); +const faker = require("faker"); module.exports = { up: async (queryInterface, Sequelize) => { // 新增:依照DOD需求的兩個測試帳號 - await queryInterface.bulkInsert( - 'Users', - [ - { - id: 1, - email: 'root@example.com', - password: await bcrypt.hash('12345678', 10), - role: 'admin', - name: 'Admin', - account: 'root', - avatar: `https://loremflickr.com/320/240/man/?random=${ - Math.random() * 100 - }`, - cover: `https://loremflickr.com/1440/480/city/?random=${ - Math.random() * 100 - }`, - introduction: faker.lorem.text().substring(0, 160), - created_at: new Date(), - updated_at: new Date() - }, - { - id: 2, - email: 'user1@example.com', - password: await bcrypt.hash('12345678', 10), - role: 'user', - name: 'User1', - account: 'user1', - avatar: `https://loremflickr.com/320/240/man/?random=${ - Math.random() * 100 - }`, - cover: `https://loremflickr.com/1440/480/city/?random=${ - Math.random() * 100 - }`, - introduction: faker.lorem.text().substring(0, 160), - created_at: new Date(), - updated_at: new Date() - } - ], - {} - ) + const data = []; + const admin = { + id: 1, + email: "root@example.com", + password: await bcrypt.hash("12345678", 10), + role: "admin", + name: "Admin", + account: "root", + avatar: `https://loremflickr.com/320/240/man/?random=${ + Math.random() * 100 + }`, + cover: `https://loremflickr.com/1440/480/city/?random=${ + Math.random() * 100 + }`, + introduction: faker.lorem.text().substring(0, 160), + created_at: new Date(), + updated_at: new Date(), + }; + data.push(admin); + + for (let i = 1; i <= 50; i++) { + const user = { + id: i + 1, + email: `user${i}@example.com`, + password: await bcrypt.hash("12345678", 10), + role: "user", + name: `User${i}`, + account: `user${i}`, + avatar: `https://loremflickr.com/320/240/man/?random=${ + Math.random() * 100 + }`, + cover: `https://loremflickr.com/1440/480/city/?random=${ + Math.random() * 100 + }`, + introduction: faker.lorem.text().substring(0, 160), + created_at: new Date(), + updated_at: new Date(), + }; + data.push(user); + } + + await queryInterface.bulkInsert("Users", data, {}); }, down: async (queryInterface, Sequelize) => { - await queryInterface.bulkDelete('Users', {}) - } -} + await queryInterface.bulkDelete("Users", {}); + }, +}; From 64ba901e77de1496a88c40368ba3584943c07583 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 22 Aug 2023 12:00:32 +0800 Subject: [PATCH 014/170] fix: getTweets --- controllers/apis/admin-controller.js | 98 ++++++++++++----------- models/tweet.js | 28 ++++--- models/user.js | 41 +++++----- seeders/20230821044414-users-seed-file.js | 42 +++++----- 4 files changed, 107 insertions(+), 102 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 92afca18d9..bdafc75dc6 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -1,5 +1,5 @@ -const db = require('../../models') -const { User, Tweet, Like } = db +const db = require("../../models"); +const { User, Tweet, Like } = db; // const bcrypt = require('bcrypt-nodejs') const adminController = { @@ -9,56 +9,58 @@ const adminController = { raw: true, attributes: { exclude: [ - 'email', - 'introduction', - 'password', - 'updatedAt', - 'createdAt' - ] + "email", + "introduction", + "password", + "updatedAt", + "createdAt", + ], }, - where: { role: 'user' } - } + where: { role: "user" }, + }; User.findAll(options) - .then(users => { - users.forEach(user => { + .then((users) => { + users.forEach((user) => { if (user.introduction) { - user.introduction = user.introduction.substring(0, 50) + user.introduction = user.introduction.substring(0, 50); } - }) - res.status(200).json(users) + }); + res.status(200).json(users); }) - .catch(error => { + .catch((error) => { res.status(500).json({ - status: 'error', - message: error - }) - }) + status: "error", + message: error, + }); + }); }, // Admin取得所有貼文 getTweets: (req, res) => { const options = { - attributes: ['id', 'description', 'createdAt'], + raw: true, + nest: true, + attributes: ["id", "description", "createdAt"], include: [ { model: User, - attributes: ['id', 'account', 'name', 'avatar'], - as: 'Author' - } - ] - } + attributes: ["id", "account", "name", "avatar"], + as: "author", + }, + ], + }; return Tweet.findAll(options) - .then(tweets => { - tweets.forEach(tweet => { - tweet.description = tweet.description.substring(0, 50) - }) - return res.status(200).json(tweets) + .then((tweets) => { + tweets.forEach((tweet) => { + tweet.description = tweet.description.substring(0, 50); + }); + return res.status(200).json(tweets); }) .catch(() => res.status(500).json({ - status: 'error', - message: 'errorrr' + status: "error", + message: "errorrr", }) - ) + ); }, // Admin刪除一篇貼文 deleteTweet: (req, cb) => { @@ -66,32 +68,32 @@ const adminController = { Tweet.destroy({ where: { id: req.params.id }, raw: true, - nest: true + nest: true, }), Like.destroy({ where: { TweetId: req.params.id }, raw: true, - nest: true - }) + nest: true, + }), ]) - .then(tweet => { + .then((tweet) => { if (!tweet) { throw new Error( - '此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除' - ) + "此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除" + ); } return cb(null, { - status: 'success', - message: '刪除貼文成功' - }) + status: "success", + message: "刪除貼文成功", + }); }) - .catch(err => cb(err)) + .catch((err) => cb(err)); }, // Admin 登入 signIn: (req, res) => { // 未完成 - const { email, password } = req.body - } -} + const { email, password } = req.body; + }, +}; -module.exports = adminController +module.exports = adminController; diff --git a/models/tweet.js b/models/tweet.js index 8de1f496b0..c82e9ed855 100644 --- a/models/tweet.js +++ b/models/tweet.js @@ -1,7 +1,5 @@ 'use strict' -const { - Model -} = require('sequelize') +const { Model } = require('sequelize') module.exports = (sequelize, DataTypes) => { class Tweet extends Model { /** @@ -13,16 +11,20 @@ module.exports = (sequelize, DataTypes) => { // define association here Tweet.hasMany(models.Reply, { foreignKey: 'tweetId' }) Tweet.hasMany(models.Like, { foreignKey: 'tweetId' }) + Tweet.belongsTo(models.User, { foreignKey: 'userId', as: 'author' }) } - }; - Tweet.init({ - description: DataTypes.TEXT, - UserId: DataTypes.INTEGER - }, { - sequelize, - modelName: 'Tweet', - tableName: 'Tweets', - underscored: true - }) + } + Tweet.init( + { + description: DataTypes.TEXT, + UserId: DataTypes.INTEGER + }, + { + sequelize, + modelName: 'Tweet', + tableName: 'Tweets', + underscored: true + } + ) return Tweet } diff --git a/models/user.js b/models/user.js index 74c077701c..09d455ab14 100644 --- a/models/user.js +++ b/models/user.js @@ -1,7 +1,5 @@ 'use strict' -const { - Model -} = require('sequelize') +const { Model } = require('sequelize') module.exports = (sequelize, DataTypes) => { class User extends Model { /** @@ -11,7 +9,7 @@ module.exports = (sequelize, DataTypes) => { */ static associate (models) { // define association here - User.hasMany(models.Tweet, { foreignKey: 'userId' }) + User.hasMany(models.Tweet, { foreignKey: 'userId', as: 'author' }) User.hasMany(models.Reply, { foreignKey: 'userId' }) User.hasMany(models.Like, { foreignKey: 'userId' }) User.belongsToMany(models.User, { @@ -25,21 +23,24 @@ module.exports = (sequelize, DataTypes) => { as: 'Followers' }) } - }; - User.init({ - name: DataTypes.STRING, - email: DataTypes.STRING, - password: DataTypes.STRING, - account: DataTypes.STRING, - introduction: DataTypes.TEXT, - avatar: DataTypes.STRING, - cover: DataTypes.STRING, - role: DataTypes.STRING - }, { - sequelize, - modelName: 'User', - tableName: 'Users', - underscored: true - }) + } + User.init( + { + name: DataTypes.STRING, + email: DataTypes.STRING, + password: DataTypes.STRING, + account: DataTypes.STRING, + introduction: DataTypes.TEXT, + avatar: DataTypes.STRING, + cover: DataTypes.STRING, + role: DataTypes.STRING + }, + { + sequelize, + modelName: 'User', + tableName: 'Users', + underscored: true + } + ) return User } diff --git a/seeders/20230821044414-users-seed-file.js b/seeders/20230821044414-users-seed-file.js index 01d1ad5898..b27e3c252a 100644 --- a/seeders/20230821044414-users-seed-file.js +++ b/seeders/20230821044414-users-seed-file.js @@ -1,18 +1,18 @@ -"use strict"; -const bcrypt = require("bcrypt"); -const faker = require("faker"); +'use strict' +const bcrypt = require('bcrypt') +const faker = require('faker') module.exports = { up: async (queryInterface, Sequelize) => { // 新增:依照DOD需求的兩個測試帳號 - const data = []; + const data = [] const admin = { id: 1, - email: "root@example.com", - password: await bcrypt.hash("12345678", 10), - role: "admin", - name: "Admin", - account: "root", + email: 'root@example.com', + password: await bcrypt.hash('12345678', 10), + role: 'admin', + name: 'Admin', + account: 'root', avatar: `https://loremflickr.com/320/240/man/?random=${ Math.random() * 100 }`, @@ -21,16 +21,16 @@ module.exports = { }`, introduction: faker.lorem.text().substring(0, 160), created_at: new Date(), - updated_at: new Date(), - }; - data.push(admin); + updated_at: new Date() + } + data.push(admin) for (let i = 1; i <= 50; i++) { const user = { id: i + 1, email: `user${i}@example.com`, - password: await bcrypt.hash("12345678", 10), - role: "user", + password: await bcrypt.hash('12345678', 10), + role: 'user', name: `User${i}`, account: `user${i}`, avatar: `https://loremflickr.com/320/240/man/?random=${ @@ -41,15 +41,15 @@ module.exports = { }`, introduction: faker.lorem.text().substring(0, 160), created_at: new Date(), - updated_at: new Date(), - }; - data.push(user); + updated_at: new Date() + } + data.push(user) } - await queryInterface.bulkInsert("Users", data, {}); + await queryInterface.bulkInsert('Users', data, {}) }, down: async (queryInterface, Sequelize) => { - await queryInterface.bulkDelete("Users", {}); - }, -}; + await queryInterface.bulkDelete('Users', {}) + } +} From 8d670a1b093773651b4b71e6c6083d07a381f4e1 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 22 Aug 2023 12:40:41 +0800 Subject: [PATCH 015/170] fix: bugs --- controllers/apis/admin-controller.js | 105 +++++++++++---------- seeders/20230821074916-tweets-seed-file.js | 2 +- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index bdafc75dc6..39ddf039c2 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -1,5 +1,5 @@ -const db = require("../../models"); -const { User, Tweet, Like } = db; +const db = require('../../models') +const { User, Tweet, Like } = db // const bcrypt = require('bcrypt-nodejs') const adminController = { @@ -9,91 +9,96 @@ const adminController = { raw: true, attributes: { exclude: [ - "email", - "introduction", - "password", - "updatedAt", - "createdAt", - ], + 'email', + 'introduction', + 'password', + 'updatedAt', + 'createdAt' + ] }, - where: { role: "user" }, - }; + where: { role: 'user' } + } User.findAll(options) - .then((users) => { - users.forEach((user) => { + .then(users => { + users.forEach(user => { if (user.introduction) { - user.introduction = user.introduction.substring(0, 50); + user.introduction = user.introduction.substring(0, 50) } - }); - res.status(200).json(users); + }) + res.status(200).json(users) }) - .catch((error) => { + .catch(error => { res.status(500).json({ - status: "error", - message: error, - }); - }); + status: 'error', + message: error + }) + }) }, // Admin取得所有貼文 getTweets: (req, res) => { const options = { raw: true, nest: true, - attributes: ["id", "description", "createdAt"], + attributes: ['id', 'description', 'createdAt'], include: [ { model: User, - attributes: ["id", "account", "name", "avatar"], - as: "author", - }, - ], - }; + attributes: ['id', 'account', 'name', 'avatar'], + as: 'author' + } + ] + } return Tweet.findAll(options) - .then((tweets) => { - tweets.forEach((tweet) => { - tweet.description = tweet.description.substring(0, 50); - }); - return res.status(200).json(tweets); + .then(tweets => { + tweets.forEach(tweet => { + tweet.description = tweet.description.substring(0, 50) + }) + return res.status(200).json(tweets) }) .catch(() => res.status(500).json({ - status: "error", - message: "errorrr", + status: 'error', + message: 'errorrr' }) - ); + ) }, // Admin刪除一篇貼文 - deleteTweet: (req, cb) => { + deleteTweet: (req, res) => { return Promise.all([ Tweet.destroy({ where: { id: req.params.id }, raw: true, - nest: true, + nest: true }), Like.destroy({ where: { TweetId: req.params.id }, raw: true, - nest: true, - }), + nest: true + }) ]) - .then((tweet) => { + .then(tweet => { if (!tweet) { throw new Error( - "此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除" - ); + '此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除' + ) } - return cb(null, { - status: "success", - message: "刪除貼文成功", - }); + return res.status(200).json({ + status: 'success', + message: 'Successfully delete tweet.' + }) }) - .catch((err) => cb(err)); + .catch(() => + res.status(500).json({ + status: 'error', + message: 'error' + }) + ) }, // Admin 登入 signIn: (req, res) => { // 未完成 - const { email, password } = req.body; - }, -}; + const { email, password } = req.body + } +} -module.exports = adminController; +module.exports = adminController diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index d9a406a4a3..f97863ecf3 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -5,7 +5,7 @@ module.exports = { up: async (queryInterface, Sequelize) => { const data = [] // eslint-disable-next-line array-callback-return - Array.from({ length: 5 }).map((user, i) => { + Array.from({ length: 10 }).map((user, i) => { for (let j = 0; j < 10; ++j) { data.push({ id: j * 10 + i + 1, From 52e4871b62d64f72eb0c091e9ab5df3d4f8de836 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 22 Aug 2023 14:57:48 +0800 Subject: [PATCH 016/170] chore: tweet table add replyCount, likeCount --- config/passport.js | 47 ++++- controllers/apis/admin-controller.js | 2 +- migrations/20230820131455-create-tweet.js | 11 ++ models/tweet.js | 4 +- package-lock.json | 204 ++++++++++++++++++++++ package.json | 2 + 6 files changed, 267 insertions(+), 3 deletions(-) diff --git a/config/passport.js b/config/passport.js index 4ca5eefed6..6027b080d8 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,3 +1,48 @@ const passport = require('passport') - +const LocalStrategy = require('passport-local') +const bcrypt = require('bcryptjs') +const db = require('../models') +const User = db.User +passport.use( + new LocalStrategy( + // customize user field + { + usernameField: 'email', + passwordField: 'password', + passReqToCallback: true + }, + // authenticate user + (req, email, password, cb) => { + User.findOne({ where: { email } }).then(user => { + if (!user) { + return cb( + null, + false, + req.flash('error_messages', '帳號或密碼輸入錯誤!') + ) + } + bcrypt.compare(password, user.password).then(res => { + if (!res) { + return cb( + null, + false, + req.flash('error_messages', '帳號或密碼輸入錯誤!') + ) + } + return cb(null, user) + }) + }) + } + ) +) +// serialize and deserialize user +passport.serializeUser((user, cb) => { + cb(null, user.id) +}) +passport.deserializeUser((id, cb) => { + User.findByPk(id).then(user => { + console.log(user) // 暫時添加 + return cb(null, user.toJSON()) + }) +}) module.exports = passport diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 39ddf039c2..b85c265291 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -39,7 +39,7 @@ const adminController = { const options = { raw: true, nest: true, - attributes: ['id', 'description', 'createdAt'], + attributes: ['id', 'description', 'replyCount', 'likeCount', 'createdAt'], include: [ { model: User, diff --git a/migrations/20230820131455-create-tweet.js b/migrations/20230820131455-create-tweet.js index 39df6eb3c1..66d5bab311 100644 --- a/migrations/20230820131455-create-tweet.js +++ b/migrations/20230820131455-create-tweet.js @@ -16,6 +16,17 @@ module.exports = { allowNull: false, defaultValue: 1 }, + like_count: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 0 + }, + reply_count: { + type: Sequelize.INTEGER, + allowNull: false, + defaultValue: 0 + }, + created_at: { allowNull: false, type: Sequelize.DATE diff --git a/models/tweet.js b/models/tweet.js index c82e9ed855..3aafa8a15f 100644 --- a/models/tweet.js +++ b/models/tweet.js @@ -17,7 +17,9 @@ module.exports = (sequelize, DataTypes) => { Tweet.init( { description: DataTypes.TEXT, - UserId: DataTypes.INTEGER + UserId: DataTypes.INTEGER, + likeCount: DataTypes.INTEGER, + replyCount: DataTypes.INTEGER }, { sequelize, diff --git a/package-lock.json b/package-lock.json index 8c4686b9fc..d686b25bc1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,10 +19,12 @@ "express": "^4.16.4", "express-session": "^1.17.3", "faker": "^5.5.3", + "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", "mysql2": "^2.3.0", "passport": "^0.4.0", + "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", "sequelize": "^6.6.5", "sequelize-cli": "^6.2.0", @@ -730,6 +732,11 @@ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/builtins": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", @@ -1188,6 +1195,14 @@ "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/editorconfig": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", @@ -3549,6 +3564,32 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -3587,6 +3628,25 @@ "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3647,12 +3707,47 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -4363,6 +4458,15 @@ "node": ">= 0.4.0" } }, + "node_modules/passport-jwt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", + "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", + "dependencies": { + "jsonwebtoken": "^8.2.0", + "passport-strategy": "^1.0.0" + } + }, "node_modules/passport-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", @@ -6568,6 +6672,11 @@ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "builtins": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", @@ -6925,6 +7034,14 @@ "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "editorconfig": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", @@ -8663,6 +8780,30 @@ "graceful-fs": "^4.1.6" } }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, "jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -8694,6 +8835,25 @@ "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -8744,12 +8904,47 @@ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -9307,6 +9502,15 @@ "pause": "0.0.1" } }, + "passport-jwt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", + "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", + "requires": { + "jsonwebtoken": "^8.2.0", + "passport-strategy": "^1.0.0" + } + }, "passport-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", diff --git a/package.json b/package.json index 340c61b060..fa79350203 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,12 @@ "express": "^4.16.4", "express-session": "^1.17.3", "faker": "^5.5.3", + "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", "mysql2": "^2.3.0", "passport": "^0.4.0", + "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", "sequelize": "^6.6.5", "sequelize-cli": "^6.2.0", From b487ff7582c7a5248a1526fbd1e12ddcc0f63a67 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Tue, 22 Aug 2023 21:14:15 +0800 Subject: [PATCH 017/170] feat: add Procfile --- Procfile | 1 + 1 file changed, 1 insertion(+) create mode 100644 Procfile diff --git a/Procfile b/Procfile new file mode 100644 index 0000000000..6feca7ecec --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: NODE_ENV=production node app.js \ No newline at end of file From 8a0f86830d5552bd72fb575d4ba2b6b5969cda01 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 22 Aug 2023 22:21:35 +0800 Subject: [PATCH 018/170] feat: admin login --- .env.example | 1 + app.js | 4 ++++ config/passport.js | 28 +++++++++------------------- controllers/apis/admin-controller.js | 21 ++++++++++++++++++--- routes/modules/admin.js | 7 ++++++- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/.env.example b/.env.example index e69de29bb2..11ab5576d6 100644 --- a/.env.example +++ b/.env.example @@ -0,0 +1 @@ +JWT_SECRET= \ No newline at end of file diff --git a/app.js b/app.js index a3b747e7df..bb62993e39 100644 --- a/app.js +++ b/app.js @@ -6,12 +6,16 @@ const helpers = require('./_helpers') const bodyParser = require('body-parser') const session = require('express-session') const routes = require('./routes') +const passport = require('./config/passport') // 增加這行,引入 Passport const app = express() // bodyparser設定 app.use(bodyParser.urlencoded({ extended: true })) app.use(bodyParser.json()) +// passport 初始化 +app.use(passport.initialize()) +app.use(passport.session()) const port = process.env.PORT || 3000 diff --git a/config/passport.js b/config/passport.js index 6027b080d8..56a530d50e 100644 --- a/config/passport.js +++ b/config/passport.js @@ -7,27 +7,19 @@ passport.use( new LocalStrategy( // customize user field { - usernameField: 'email', + usernameField: 'account', passwordField: 'password', - passReqToCallback: true + passReqToCallback: false }, // authenticate user - (req, email, password, cb) => { - User.findOne({ where: { email } }).then(user => { + (account, password, cb) => { + User.findOne({ where: { account } }).then(user => { if (!user) { - return cb( - null, - false, - req.flash('error_messages', '帳號或密碼輸入錯誤!') - ) + return cb(null, false, { message: '帳號或密碼輸入錯誤!' }) } bcrypt.compare(password, user.password).then(res => { if (!res) { - return cb( - null, - false, - req.flash('error_messages', '帳號或密碼輸入錯誤!') - ) + return cb(null, false, { message: '帳號或密碼輸入錯誤!' }) } return cb(null, user) }) @@ -39,10 +31,8 @@ passport.use( passport.serializeUser((user, cb) => { cb(null, user.id) }) -passport.deserializeUser((id, cb) => { - User.findByPk(id).then(user => { - console.log(user) // 暫時添加 - return cb(null, user.toJSON()) - }) +passport.deserializeUser(async (id, cb) => { + const user = await User.findByPk(id) + return cb(null, user.toJSON()) }) module.exports = passport diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index b85c265291..5f829fe905 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -1,6 +1,7 @@ const db = require('../../models') const { User, Tweet, Like } = db // const bcrypt = require('bcrypt-nodejs') +const jwt = require('jsonwebtoken') const adminController = { // Admin 取得所有使用者 @@ -95,9 +96,23 @@ const adminController = { ) }, // Admin 登入 - signIn: (req, res) => { - // 未完成 - const { email, password } = req.body + signIn: (req, res, next) => { + try { + const userData = req.user.toJSON() + const token = jwt.sign(userData, process.env.JWT_SECRET, { + expiresIn: '30d' + }) + res.json({ + status: 'success', + data: { + token, + user: userData + } + }) + } catch (err) { + console.log(err.message) + // next(err); + } } } diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 41f40a4c60..e384997d77 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -1,8 +1,13 @@ const express = require('express') const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') +const passport = require('passport') -router.post('/login', adminController.signIn) +router.post( + '/login', + passport.authenticate('local', { session: false }), + adminController.signIn +) router.get('/users', adminController.getUsers) router.delete('/tweets/:id', adminController.deleteTweet) router.get('/tweets', adminController.getTweets) From 28b216496e22d9059941f9b4cca7b13518fde6dc Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Tue, 22 Aug 2023 21:19:19 +0800 Subject: [PATCH 019/170] bug: add cors, heroku and bug on dotenv --- app.js | 5 ++++- config/config.json | 7 ++----- package-lock.json | 23 ++++++++++++++++++++++- package.json | 1 + 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/app.js b/app.js index a3b747e7df..5442836a76 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,9 @@ -if (process.NODE_ENV !== 'production') { +if (process.env.NODE_ENV !== 'production') { require('dotenv').config() } +// require('dotenv').config() const express = require('express') +const cors = require('cors') const helpers = require('./_helpers') const bodyParser = require('body-parser') const session = require('express-session') @@ -20,6 +22,7 @@ function authenticated (req, res, next) { // passport.authenticate('jwt', { ses... } +app.use(cors()) app.use(routes) app.get('/', (req, res) => res.send('Hello World!')) diff --git a/config/config.json b/config/config.json index 8920098a42..8b6bde1566 100644 --- a/config/config.json +++ b/config/config.json @@ -15,11 +15,7 @@ "logging": false }, "production": { - "username": "root", - "password": null, - "database": "database_production", - "host": "127.0.0.1", - "dialect": "mysql" + "use_env_variable": "MYSQL_DATABASE_URL" }, "travis": { "username": "travis", @@ -35,3 +31,4 @@ "dialect": "mysql" } } + diff --git a/package-lock.json b/package-lock.json index d686b25bc1..fa508b89b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "body-parser": "^1.20.2", "chai": "^4.2.0", "connect-flash": "^0.1.1", - "dotenv": "^16.3.1", + "cors": "^2.8.5", "express": "^4.16.4", "express-session": "^1.17.3", "faker": "^5.5.3", @@ -1025,6 +1025,18 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6911,6 +6923,15 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", diff --git a/package.json b/package.json index fa79350203..d3b46bbb64 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "body-parser": "^1.20.2", "chai": "^4.2.0", "connect-flash": "^0.1.1", + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.16.4", "express-session": "^1.17.3", From 0e585291904c73ec68e23b49a24e0bd1f1ed6f8c Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Tue, 22 Aug 2023 23:47:10 +0800 Subject: [PATCH 020/170] final test --- app.js | 2 +- package-lock.json | 7033 ++++++++------------------------------------- package.json | 1 - 3 files changed, 1265 insertions(+), 5771 deletions(-) diff --git a/app.js b/app.js index 5442836a76..ba3619d352 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,7 @@ if (process.env.NODE_ENV !== 'production') { require('dotenv').config() } -// require('dotenv').config() +require('dotenv').config() const express = require('express') const cors = require('cors') const helpers = require('./_helpers') diff --git a/package-lock.json b/package-lock.json index fa508b89b9..0cf04ccedd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,7 @@ { "name": "test", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -65,9 +65,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.7.0.tgz", + "integrity": "sha512-+HencqxU7CFJnQb7IKtuNBqS6Yx3Tz4kOL8BJXo+JyeiBm5MEX6pO8onXDkjrkCRlfYXS1Axro15ZjVFe9YgsA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -96,12 +96,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/@eslint/eslintrc/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -119,48 +113,12 @@ } } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@eslint/eslintrc/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { "version": "8.47.0", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", @@ -201,18 +159,6 @@ } } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@humanwhocodes/config-array/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -257,20 +203,6 @@ "node-pre-gyp": "bin/node-pre-gyp" } }, - "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -306,10 +238,15 @@ "node": ">= 8" } }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" + }, "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dependencies": { "type-detect": "4.0.8" } @@ -333,9 +270,17 @@ } }, "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==" + }, + "node_modules/@types/debug": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", + "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "dependencies": { + "@types/ms": "*" + } }, "node_modules/@types/json5": { "version": "0.0.29", @@ -343,10 +288,20 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, "node_modules/@types/node": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz", - "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==" + "version": "20.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.2.tgz", + "integrity": "sha512-5j/lXt7unfPOUlrKC34HIaedONleyLtwkKggiD/0uuMfT8gg2EOpg0dz4lCD15Ga7muC+1WzJZAjIB9simWd6Q==" + }, + "node_modules/@types/validator": { + "version": "13.11.1", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", + "integrity": "sha512-d/MUkJYdOeKycmm75Arql4M5+UuXmf4cHdHKsyw1GcvnNgL6s77UkgSgJ8TE/rI5PYsnwYq5jkcWBLuN/MpQ1A==" }, "node_modules/abbrev": { "version": "1.1.1", @@ -443,29 +398,27 @@ } }, "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -483,26 +436,11 @@ "node": ">=10" } }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/array-buffer-byte-length": { "version": "1.0.0", @@ -519,7 +457,7 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/array-includes": { "version": "3.1.6", @@ -595,6 +533,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array.prototype.reduce": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", + "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.tosorted": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", @@ -647,9 +603,17 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -682,7 +646,7 @@ "node_modules/bcrypt-nodejs": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", - "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=", + "integrity": "sha512-NmTbLm867btBHCBZ222FQXkQKzecB0KG6pTXFa6NeTVZaSnLfCsx7EK2PL3J+kX8xJThUquEBbhimRCKKZX9zA==", "deprecated": "bcrypt-nodejs is no longer actively maintained. Please use bcrypt or bcryptjs. See https://github.com/kelektiv/node.bcrypt.js/wiki/bcrypt-vs-brypt.js to learn more about these two options" }, "node_modules/bcryptjs": { @@ -746,21 +710,6 @@ "semver": "^7.0.0" } }, - "node_modules/builtins/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -799,13 +748,13 @@ } }, "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", @@ -816,33 +765,25 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" + "node": ">=10" }, - "engines": { - "node": ">=4" + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", "engines": { "node": "*" } @@ -856,16 +797,18 @@ } }, "node_modules/cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", + "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", "dependencies": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", + "d": "^1.0.1", + "es5-ext": "^0.10.61", "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.10" } }, "node_modules/cliui": { @@ -886,6 +829,19 @@ "node": ">=6" } }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, "node_modules/cliui/node_modules/string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -911,17 +867,20 @@ } }, "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/color-support": { "version": "1.1.3", @@ -944,9 +903,12 @@ } }, "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } }, "node_modules/component-emitter": { "version": "1.3.0", @@ -957,7 +919,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/config-chain": { "version": "1.1.13", @@ -971,7 +933,7 @@ "node_modules/connect-flash": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", - "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=", + "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA==", "engines": { "node": ">= 0.4.0" } @@ -1001,9 +963,9 @@ } }, "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -1011,12 +973,12 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, "node_modules/core-util-is": { @@ -1051,21 +1013,6 @@ "node": ">= 8" } }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -1086,20 +1033,20 @@ "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "engines": { "node": ">=0.10.0" } }, "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dependencies": { "type-detect": "^4.0.0" }, "engines": { - "node": ">=0.12" + "node": ">=6" } }, "node_modules/deep-is": { @@ -1126,7 +1073,7 @@ "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "engines": { "node": ">=0.4.0" @@ -1138,9 +1085,9 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, "node_modules/denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", "engines": { "node": ">=0.10" } @@ -1203,9 +1150,9 @@ } }, "node_modules/dottie": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", - "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", @@ -1216,47 +1163,58 @@ } }, "node_modules/editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" }, "bin": { "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" } }, - "node_modules/editorconfig/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "node_modules/editorconfig/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==", "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "balanced-match": "^1.0.0" } }, - "node_modules/editorconfig/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } @@ -1322,22 +1280,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" }, "node_modules/es-iterator-helpers": { "version": "1.0.13", @@ -1400,9 +1346,9 @@ } }, "node_modules/es5-ext": { - "version": "0.10.60", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", - "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", "hasInstallScript": true, "dependencies": { "es6-iterator": "^2.0.3", @@ -1416,7 +1362,7 @@ "node_modules/es6-iterator": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "dependencies": { "d": "1", "es5-ext": "^0.10.35", @@ -1443,17 +1389,29 @@ "es6-symbol": "^3.1.1" } }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { @@ -1736,18 +1694,6 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint-plugin-import/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1764,9 +1710,9 @@ } }, "node_modules/eslint-plugin-n": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.1.tgz", - "integrity": "sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==", + "version": "16.0.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.2.tgz", + "integrity": "sha512-Y66uDfUNbBzypsr0kELWrIz+5skicECrLUqlWuXawNSLUq3ltGlCwu6phboYYOTSnoTdHgTLrc+5Ydo6KjzZog==", "dev": true, "peer": true, "dependencies": { @@ -1789,35 +1735,6 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-plugin-n/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-n/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "peer": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-plugin-promise": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", @@ -1872,18 +1789,6 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-react/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.4", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", @@ -1965,70 +1870,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/eslint/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2046,226 +1887,87 @@ } } }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "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==", "dev": true, "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "estraverse": "^5.1.0" }, "engines": { - "node": "*" + "node": ">=0.10" } }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "dependencies": { - "yocto-queue": "^0.1.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.0" } }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4.0" } }, - "node_modules/eslint/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" } }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } @@ -2273,44 +1975,45 @@ "node_modules/event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "dependencies": { "d": "1", "es5-ext": "~0.10.14" } }, "node_modules/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.2", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.2", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.7", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", + "send": "0.18.0", + "serve-static": "1.15.0", "setprototypeof": "1.2.0", - "statuses": "~1.5.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -2337,78 +2040,44 @@ "node": ">= 0.8.0" } }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/express/node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" - } - }, - "node_modules/express/node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/express/node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { "bytes": "3.1.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -2417,17 +2086,17 @@ } }, "node_modules/ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "dependencies": { - "type": "^2.5.0" + "type": "^2.7.2" } }, "node_modules/ext/node_modules/type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" }, "node_modules/extend": { "version": "3.0.2", @@ -2482,7 +2151,7 @@ "node_modules/fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==", "dev": true, "dependencies": { "is-object": "~1.0.1", @@ -2493,42 +2162,36 @@ } }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, - "node_modules/finalhandler/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "dependencies": { - "locate-path": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { @@ -2604,22 +2267,23 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } }, "node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=10" } }, "node_modules/fs-minipass": { @@ -2647,7 +2311,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/function-bind": { "version": "1.1.1", @@ -2698,51 +2362,6 @@ "node": ">=10" } }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/gauge/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -2762,7 +2381,7 @@ "node_modules/get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", "engines": { "node": "*" } @@ -2877,9 +2496,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", @@ -2915,11 +2534,11 @@ } }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/has-property-descriptors": { @@ -2997,14 +2616,6 @@ "node": ">= 0.8" } }, - "node_modules/http-errors/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -3084,9 +2695,9 @@ } }, "node_modules/inflection": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz", - "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", "engines": [ "node >= 0.4.0" ] @@ -3094,7 +2705,7 @@ "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3271,11 +2882,11 @@ } }, "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/is-generator-function": { @@ -3365,7 +2976,7 @@ "node_modules/is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" }, "node_modules/is-regex": { "version": "1.1.4", @@ -3478,15 +3089,14 @@ } }, "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/iterator.prototype": { "version": "1.1.0", @@ -3502,14 +3112,14 @@ } }, "node_modules/js-beautify": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", - "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz", + "integrity": "sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==", "dependencies": { "config-chain": "^1.1.13", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "nopt": "^5.0.0" + "editorconfig": "^1.0.3", + "glob": "^8.1.0", + "nopt": "^6.0.0" }, "bin": { "css-beautify": "js/bin/css-beautify.js", @@ -3517,22 +3127,73 @@ "js-beautify": "js/bin/js-beautify.js" }, "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "node_modules/js-beautify/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==", + "dependencies": { + "balanced-match": "^1.0.0" + } }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "node_modules/js-beautify/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "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/js-beautify/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-beautify/node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" @@ -3569,9 +3230,12 @@ } }, "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -3602,6 +3266,14 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -3617,24 +3289,6 @@ "node": ">=4.0" } }, - "node_modules/jsx-ast-utils/node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/just-extend": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", @@ -3698,15 +3352,18 @@ } }, "node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -3717,7 +3374,7 @@ "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" }, "node_modules/lodash.includes": { "version": "4.3.0", @@ -3771,6 +3428,70 @@ "node": ">=4" } }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/log-symbols/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", @@ -3789,9 +3510,9 @@ } }, "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", "dependencies": { "get-func-name": "^2.0.0" } @@ -3810,7 +3531,7 @@ "node_modules/lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", "dependencies": { "es5-ext": "~0.10.2" } @@ -3840,7 +3561,7 @@ "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "engines": { "node": ">= 0.6" } @@ -3863,7 +3584,7 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/method-override": { "version": "3.0.0", @@ -3890,7 +3611,7 @@ "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -3926,9 +3647,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3937,9 +3658,12 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minipass": { "version": "5.0.0", @@ -4021,6 +3745,14 @@ "node": ">= 6.0.0" } }, + "node_modules/mocha/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/mocha/node_modules/debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -4030,94 +3762,227 @@ "ms": "^2.1.1" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } }, - "node_modules/module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true + "node_modules/mocha/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } }, - "node_modules/moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==", + "node_modules/mocha/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "engines": { - "node": "*" + "node": ">=4" } }, - "node_modules/moment-timezone": { - "version": "0.5.34", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", - "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", + "node_modules/mocha/node_modules/js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dependencies": { - "moment": ">= 2.9.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": "*" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "node_modules/mocha/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } }, - "node_modules/mysql2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.0.tgz", - "integrity": "sha512-0t5Ivps5Tdy5YHk5NdKwQhe/4Qyn2pload+S+UooDBvsqngtzujG1BaTWBihQLfeKO3t3122/GtusBtmHEHqww==", + "node_modules/mocha/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dependencies": { - "denque": "^1.4.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.2", - "long": "^4.0.0", - "lru-cache": "^6.0.0", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 8.0" + "node": "*" } }, - "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/mocha/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/mocha/node_modules/object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/named-placeholders": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", - "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", + "node_modules/mocha/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dependencies": { - "lru-cache": "^4.1.3" + "p-try": "^2.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/named-placeholders/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "node_modules/mocha/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/named-placeholders/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "node_modules/mocha/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/mocha/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==", + "dev": true + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.43", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", + "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/mysql2": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", + "integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==", + "dependencies": { + "denque": "^2.0.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^4.0.0", + "lru-cache": "^6.0.0", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } }, "node_modules/natural-compare": { "version": "1.4.0", @@ -4153,7 +4018,7 @@ "node_modules/nise/node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" }, "node_modules/nise/node_modules/path-to-regexp": { "version": "1.8.0", @@ -4177,6 +4042,14 @@ "semver": "^5.7.0" } }, + "node_modules/node-environment-flags/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/node-fetch": { "version": "2.6.13", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", @@ -4246,17 +4119,20 @@ } }, "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.entries": { @@ -4291,13 +4167,15 @@ } }, "node_modules/object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz", + "integrity": "sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==", "dependencies": { + "array.prototype.reduce": "^1.0.5", "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" + "define-properties": "^1.2.0", + "es-abstract": "^1.21.2", + "safe-array-concat": "^1.0.0" }, "engines": { "node": ">= 0.8" @@ -4370,7 +4248,7 @@ "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dependencies": { "wrappy": "1" } @@ -4393,28 +4271,33 @@ } }, "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "dependencies": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "dependencies": { - "p-limit": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-try": { @@ -4471,18 +4354,38 @@ } }, "node_modules/passport-jwt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", - "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", "dependencies": { - "jsonwebtoken": "^8.2.0", + "jsonwebtoken": "^9.0.0", "passport-strategy": "^1.0.0" } }, + "node_modules/passport-jwt/node_modules/jsonwebtoken": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/passport-jwt/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/passport-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", "dependencies": { "passport-strategy": "1.x.x" }, @@ -4493,23 +4396,24 @@ "node_modules/passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", "engines": { "node": ">= 0.4.0" } }, "node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "engines": { "node": ">=0.10.0" } @@ -4531,7 +4435,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/pathval": { "version": "1.1.1", @@ -4544,7 +4448,12 @@ "node_modules/pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" }, "node_modules/pify": { "version": "4.0.1", @@ -4568,6 +4477,67 @@ "node": ">=6" } }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4597,7 +4567,7 @@ "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -4622,11 +4592,6 @@ "resolve": "^1.11.1" } }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -4673,7 +4638,7 @@ "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", "engines": { "node": ">= 0.8" } @@ -4707,26 +4672,18 @@ "dev": true }, "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/reflect.getprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.3.tgz", @@ -4778,7 +4735,7 @@ "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "engines": { "node": ">=0.10.0" } @@ -4814,12 +4771,9 @@ } }, "node_modules/retry-as-promised": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", - "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", - "dependencies": { - "any-promise": "^1.3.0" - } + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", + "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" }, "node_modules/reusify": { "version": "1.0.4", @@ -4885,11 +4839,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4928,120 +4877,105 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { - "semver": "bin/semver" + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/send/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/send/node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "node_modules/send/node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "node_modules/send/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/seq-queue": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" }, "node_modules/sequelize": { - "version": "6.6.5", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.6.5.tgz", - "integrity": "sha512-QyRrJrDRiwuiILqTMHUA1yWOPIL12KlfmgZ3hnzQwbMvp2vJ6fzu9bYJQB+qPMosck4mBUggY4Cjoc6Et8FBIQ==", + "version": "6.32.1", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.32.1.tgz", + "integrity": "sha512-3Iv0jruv57Y0YvcxQW7BE56O7DC1BojcfIrqh6my+IQwde+9u/YnuYHzK+8kmZLhLvaziRT1eWu38nh9yVwn/g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/sequelize" + } + ], "dependencies": { - "debug": "^4.1.1", - "dottie": "^2.0.0", - "inflection": "1.13.1", - "lodash": "^4.17.20", - "moment": "^2.26.0", - "moment-timezone": "^0.5.31", - "retry-as-promised": "^3.2.0", - "semver": "^7.3.2", - "sequelize-pool": "^6.0.0", + "@types/debug": "^4.1.8", + "@types/validator": "^13.7.17", + "debug": "^4.3.4", + "dottie": "^2.0.4", + "inflection": "^1.13.4", + "lodash": "^4.17.21", + "moment": "^2.29.4", + "moment-timezone": "^0.5.43", + "pg-connection-string": "^2.6.0", + "retry-as-promised": "^7.0.4", + "semver": "^7.5.1", + "sequelize-pool": "^7.1.0", "toposort-class": "^1.0.1", - "uuid": "^8.1.0", - "validator": "^13.6.0", + "uuid": "^8.3.2", + "validator": "^13.9.0", "wkx": "^0.5.0" }, "engines": { "node": ">=10.0.0" }, "peerDependenciesMeta": { + "ibm_db": { + "optional": true + }, "mariadb": { "optional": true }, "mysql2": { "optional": true }, + "oracledb": { + "optional": true + }, "pg": { "optional": true }, "pg-hstore": { "optional": true }, + "snowflake-sdk": { + "optional": true + }, "sqlite3": { "optional": true }, @@ -5051,17 +4985,17 @@ } }, "node_modules/sequelize-cli": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", - "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", - "dependencies": { - "cli-color": "^1.4.0", - "fs-extra": "^7.0.1", - "js-beautify": "^1.8.8", - "lodash": "^4.17.5", - "resolve": "^1.5.0", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.1.tgz", + "integrity": "sha512-C3qRpy1twBsFa855qOQFSYWer8ngiaZP05/OAsT1QCUwtc6UxVNNiQ0CGUt98T9T1gi5D3TGWL6le8HWUKELyw==", + "dependencies": { + "cli-color": "^2.0.3", + "fs-extra": "^9.1.0", + "js-beautify": "^1.14.5", + "lodash": "^4.17.21", + "resolve": "^1.22.1", "umzug": "^2.3.0", - "yargs": "^13.1.0" + "yargs": "^16.2.0" }, "bin": { "sequelize": "lib/sequelize", @@ -5071,18 +5005,77 @@ "node": ">=10.0.0" } }, + "node_modules/sequelize-cli/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/sequelize-cli/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/sequelize-cli/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/sequelize-cli/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sequelize-cli/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/sequelize-pool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", - "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", + "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", "engines": { "node": ">= 10.0.0" } }, "node_modules/sequelize-test-helpers": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.2.tgz", - "integrity": "sha512-v7Yy9DKjzFA/OHLtxvFClgN2CKA9cRwxn9+6ha6xoqUzRngXdsbrmle0KD1onSqnCwVIweWlRTLJxcEl1ueozA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.3.tgz", + "integrity": "sha512-5NzQljzIDaKi+iAK5237DcemsJI1FmTPgMoE9Tu/oYZVwa6l3Lf5nF2yV0ruTrsrAKi2XWywnXFl2AATEfoBGw==", "dev": true, "engines": { "node": ">= 8.10.0" @@ -5117,29 +5110,15 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node_modules/sequelize/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.2" + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" @@ -5148,7 +5127,7 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -5189,11 +5168,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" - }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -5233,29 +5207,10 @@ "node": ">=0.3.1" } }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/sqlstring": { "version": "2.3.3", @@ -5356,64 +5311,33 @@ "eslint": ">=7.0.0" } }, - "node_modules/standard/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/standard/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dependencies": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, - "node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/string.prototype.matchall": { @@ -5478,22 +5402,14 @@ } }, "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=4" - } - }, - "node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/strip-bom": { @@ -5506,11 +5422,15 @@ } }, "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/superagent": { @@ -5544,12 +5464,48 @@ "ms": "^2.1.1" } }, + "node_modules/superagent/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/superagent/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/superagent/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/superagent/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/superagent/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/supertest": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", @@ -5564,14 +5520,14 @@ } }, "node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -5638,7 +5594,7 @@ "node_modules/toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" }, "node_modules/tr46": { "version": "0.0.3", @@ -5804,17 +5760,17 @@ } }, "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -5831,12 +5787,12 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -5850,9 +5806,9 @@ } }, "node_modules/validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", "engines": { "node": ">= 0.10" } @@ -5860,7 +5816,7 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } @@ -5889,14 +5845,18 @@ } }, "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { - "which": "bin/which" + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, "node_modules/which-boxed-primitive": { @@ -5940,12 +5900,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, "node_modules/which-collection": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", @@ -5962,9 +5916,9 @@ } }, "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" }, "node_modules/which-typed-array": { "version": "1.1.11", @@ -5992,18 +5946,57 @@ "string-width": "^1.0.2 || 2" } }, - "node_modules/wkx": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", - "dependencies": { - "@types/node": "*" + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "engines": { + "node": ">=4" } }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dependencies": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -6021,6 +6014,43 @@ "node": ">=6" } }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, "node_modules/wrap-ansi/node_modules/string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -6048,7 +6078,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/xdg-basedir": { "version": "4.0.0", @@ -6116,6 +6146,75 @@ "node": ">=6" } }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "node_modules/yargs/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/yargs/node_modules/string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -6152,4609 +6251,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@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 - }, - "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.3.0" - } - }, - "@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", - "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", - "dev": true - }, - "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "requires": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "@types/node": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz", - "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g==" - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==" - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, - "aproba": { - "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==" - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - } - }, - "array.prototype.findlastindex": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", - "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" - } - }, - "array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" - } - }, - "arraybuffer.prototype.slice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", - "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", - "requires": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - } - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" - }, - "asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.3" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "bcrypt": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", - "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.11", - "node-addon-api": "^5.0.0" - } - }, - "bcrypt-nodejs": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", - "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" - }, - "bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, - "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" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "requires": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "connect-flash": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", - "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", - "dev": true - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==" - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "dev": true - }, - "dottie": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", - "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "requires": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - } - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", - "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", - "requires": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.1", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-array-concat": "^1.0.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.10" - }, - "dependencies": { - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - } - } - }, - "es-iterator-helpers": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.13.tgz", - "integrity": "sha512-LK3VGwzvaPWobO8xzXXGRUOGw8Dcjyfk62CsY/wfHN75CwsJPbuypOYJxK6g5RyEL8YDjIWcl6jgd8foO6mmrA==", - "dev": true, - "requires": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.21.3", - "es-set-tostringtag": "^2.0.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "iterator.prototype": "^1.1.0", - "safe-array-concat": "^1.0.0" - } - }, - "es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - } - }, - "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es5-ext": { - "version": "0.10.60", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", - "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", - "requires": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "eslint": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", - "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "^8.47.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "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", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "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", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "eslint-config-standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", - "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", - "dev": true, - "requires": {} - }, - "eslint-config-standard-jsx": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", - "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", - "dev": true, - "requires": {} - }, - "eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "requires": { - "debug": "^3.2.7" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "eslint-plugin-es": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", - "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", - "dev": true, - "requires": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "dependencies": { - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-plugin-es-x": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.2.0.tgz", - "integrity": "sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==", - "dev": true, - "peer": true, - "requires": { - "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.6.0" - } - }, - "eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", - "dev": true, - "requires": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", - "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "eslint-plugin-n": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.1.tgz", - "integrity": "sha512-CDmHegJN0OF3L5cz5tATH84RPQm9kG+Yx39wIqIwPR2C0uhBGMWfbbOtetR83PQjjidA5aXMu+LEFw1jaSwvTA==", - "dev": true, - "peer": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.1.0", - "ignore": "^5.2.4", - "is-core-module": "^2.12.1", - "minimatch": "^3.1.2", - "resolve": "^1.22.2", - "semver": "^7.5.3" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "peer": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "peer": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "eslint-plugin-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "dev": true, - "requires": {} - }, - "eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", - "dev": true, - "requires": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" - }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dev": true, - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true - } - } - }, - "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==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "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 - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.19.2", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.9.7", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", - "setprototypeof": "1.2.0", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" - }, - "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", - "requires": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - } - } - }, - "express-session": { - "version": "1.17.3", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", - "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", - "requires": { - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - } - }, - "ext": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", - "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", - "requires": { - "type": "^2.5.0" - }, - "dependencies": { - "type": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", - "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "faker": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", - "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "requires": { - "is-buffer": "~2.0.3" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "requires": { - "is-callable": "^1.1.3" - } - }, - "form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "dev": true - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - } - } - }, - "generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "requires": { - "is-property": "^1.0.2" - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" - }, - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } - }, - "get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "requires": { - "define-properties": "^1.1.3" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "dependencies": { - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - } - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "inflection": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.1.tgz", - "integrity": "sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" - }, - "is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "requires": { - "which-typed-array": "^1.1.11" - } - }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "iterator.prototype": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.0.tgz", - "integrity": "sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw==", - "dev": true, - "requires": { - "define-properties": "^1.1.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "has-tostringtag": "^1.0.0", - "reflect.getprototypeof": "^1.0.3" - } - }, - "js-beautify": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", - "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", - "requires": { - "config-chain": "^1.1.13", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "nopt": "^5.0.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "requires": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "dependencies": { - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - } - } - }, - "just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "load-json-file": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - }, - "dependencies": { - "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "dev": true - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "requires": { - "chalk": "^2.0.1" - } - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", - "requires": { - "get-func-name": "^2.0.0" - } - }, - "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==", - "requires": { - "yallist": "^4.0.0" - } - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "requires": { - "es5-ext": "~0.10.2" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - } - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "method-override": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", - "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", - "requires": { - "debug": "3.1.0", - "methods": "~1.1.2", - "parseurl": "~1.3.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - } - } - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, - "moment": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz", - "integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==" - }, - "moment-timezone": { - "version": "0.5.34", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.34.tgz", - "integrity": "sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==", - "requires": { - "moment": ">= 2.9.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "mysql2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.0.tgz", - "integrity": "sha512-0t5Ivps5Tdy5YHk5NdKwQhe/4Qyn2pload+S+UooDBvsqngtzujG1BaTWBihQLfeKO3t3122/GtusBtmHEHqww==", - "requires": { - "denque": "^1.4.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.2", - "long": "^4.0.0", - "lru-cache": "^6.0.0", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "named-placeholders": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", - "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", - "requires": { - "lru-cache": "^4.1.3" - }, - "dependencies": { - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - } - } - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, - "nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", - "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "requires": { - "isarray": "0.0.1" - } - } - } - }, - "node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" - }, - "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node-fetch": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", - "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", - "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "object.groupby": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz", - "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.21.2", - "get-intrinsic": "^1.2.1" - } - }, - "object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", - "dev": true, - "requires": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "dev": true, - "requires": { - "@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" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "passport": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", - "requires": { - "passport-strategy": "1.x.x", - "pause": "0.0.1" - } - }, - "passport-jwt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", - "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", - "requires": { - "jsonwebtoken": "^8.2.0", - "passport-strategy": "^1.0.0" - } - }, - "passport-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", - "requires": { - "passport-strategy": "1.x.x" - } - }, - "passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==" - }, - "pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pkg-conf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", - "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "load-json-file": "^5.2.0" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "proxyquire": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", - "dev": true, - "requires": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "reflect.getprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.3.tgz", - "integrity": "sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.1", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - } - }, - "regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "retry-as-promised": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", - "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", - "requires": { - "any-promise": "^1.3.0" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-array-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", - "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - } - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - }, - "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "1.8.1", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" - }, - "sequelize": { - "version": "6.6.5", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.6.5.tgz", - "integrity": "sha512-QyRrJrDRiwuiILqTMHUA1yWOPIL12KlfmgZ3hnzQwbMvp2vJ6fzu9bYJQB+qPMosck4mBUggY4Cjoc6Et8FBIQ==", - "requires": { - "debug": "^4.1.1", - "dottie": "^2.0.0", - "inflection": "1.13.1", - "lodash": "^4.17.20", - "moment": "^2.26.0", - "moment-timezone": "^0.5.31", - "retry-as-promised": "^3.2.0", - "semver": "^7.3.2", - "sequelize-pool": "^6.0.0", - "toposort-class": "^1.0.1", - "uuid": "^8.1.0", - "validator": "^13.6.0", - "wkx": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "sequelize-cli": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", - "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", - "requires": { - "cli-color": "^1.4.0", - "fs-extra": "^7.0.1", - "js-beautify": "^1.8.8", - "lodash": "^4.17.5", - "resolve": "^1.5.0", - "umzug": "^2.3.0", - "yargs": "^13.1.0" - } - }, - "sequelize-pool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", - "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==" - }, - "sequelize-test-helpers": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.2.tgz", - "integrity": "sha512-v7Yy9DKjzFA/OHLtxvFClgN2CKA9cRwxn9+6ha6xoqUzRngXdsbrmle0KD1onSqnCwVIweWlRTLJxcEl1ueozA==", - "dev": true, - "requires": {} - }, - "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.2" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", - "requires": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "sinon-chai": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "requires": {} - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==" - }, - "standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.0.tgz", - "integrity": "sha512-jaDqlNSzLtWYW4lvQmU0EnxWMUGQiwHasZl5ZEIwx3S/ijZDjZOzs1y1QqKwKs5vqnFpGtizo4NOYX2s0Voq/g==", - "dev": true, - "requires": { - "eslint": "^8.41.0", - "eslint-config-standard": "17.1.0", - "eslint-config-standard-jsx": "^11.0.0", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-n": "^15.7.0", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-react": "^7.32.2", - "standard-engine": "^15.0.0", - "version-guard": "^1.1.1" - }, - "dependencies": { - "eslint-plugin-n": { - "version": "15.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", - "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", - "dev": true, - "requires": { - "builtins": "^5.0.1", - "eslint-plugin-es": "^4.1.0", - "eslint-utils": "^3.0.0", - "ignore": "^5.1.1", - "is-core-module": "^2.11.0", - "minimatch": "^3.1.2", - "resolve": "^1.22.1", - "semver": "^7.3.8" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "standard-engine": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.1.0.tgz", - "integrity": "sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==", - "dev": true, - "requires": { - "get-stdin": "^8.0.0", - "minimist": "^1.2.6", - "pkg-conf": "^3.1.0", - "xdg-basedir": "^4.0.0" - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" - } - }, - "string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" - } - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "dev": true, - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - } - } - }, - "supertest": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", - "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", - "dev": true, - "requires": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - } - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "toposort-class": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" - }, - "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 - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - } - }, - "typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "requires": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - } - }, - "typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - } - }, - "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "requires": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - } - }, - "uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "requires": { - "random-bytes": "~1.0.0" - } - }, - "umzug": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", - "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", - "requires": { - "bluebird": "^3.7.2" - } - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "version-guard": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.1.tgz", - "integrity": "sha512-MGQLX89UxmYHgDvcXyjBI0cbmoW+t/dANDppNPrno64rYr8nH4SHSuElQuSYdXGEs0mUzdQe1BY+FhVPNsAmJQ==", - "dev": true - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "requires": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } - } - }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wkx": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", - "requires": { - "@types/node": "*" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } } } diff --git a/package.json b/package.json index d3b46bbb64..dc7be88540 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ "chai": "^4.2.0", "connect-flash": "^0.1.1", "cors": "^2.8.5", - "dotenv": "^16.3.1", "express": "^4.16.4", "express-session": "^1.17.3", "faker": "^5.5.3", From c4886d622f73b79eab9dc41382cf35de25d5b5e2 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 23 Aug 2023 11:23:02 +0800 Subject: [PATCH 021/170] feat: modify config for heroku --- Procfile | 1 + config/config.json | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) create mode 100644 Procfile diff --git a/Procfile b/Procfile new file mode 100644 index 0000000000..2cbe96dff6 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: NODE_ENV=production node app.js diff --git a/config/config.json b/config/config.json index 8920098a42..5e4a51b957 100644 --- a/config/config.json +++ b/config/config.json @@ -15,11 +15,7 @@ "logging": false }, "production": { - "username": "root", - "password": null, - "database": "database_production", - "host": "127.0.0.1", - "dialect": "mysql" + "use_env_variable": "MYSQL_DATABASE_URL" }, "travis": { "username": "travis", From e1066610b39456ffb1e36781c50fd5b870d9a061 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 23 Aug 2023 12:14:12 +0800 Subject: [PATCH 022/170] fix: modify app.js require dotenv --- app.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index bb62993e39..48e6ed562f 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,7 @@ -if (process.NODE_ENV !== 'production') { - require('dotenv').config() -} +// if (process.NODE_ENV !== 'production') { +// require('dotenv').config() +// } +require('dotenv').config() const express = require('express') const helpers = require('./_helpers') const bodyParser = require('body-parser') From b26920f71de3bc8249e583f7bc8ad9bce3b7ff4d Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 23 Aug 2023 12:23:29 +0800 Subject: [PATCH 023/170] fix: modify index.js --- routes/index.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/routes/index.js b/routes/index.js index 0b0501c263..2c3fcc38f7 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,28 +1,28 @@ -const express = require('express') -const router = express.Router() +const express = require("express"); +const router = express.Router(); -const admin = require('./modules/admin') +const admin = require("./modules/admin"); -const userController = require('../controllers/apis/user-controller') -const tweetContorller = require('../controllers/apis/tweet-controller') +const userController = require("../controllers/apis/user-controller"); +const tweetContorller = require("../controllers/apis/tweet-controller"); -const { apiErrorHandler } = require('../middleware/error-handler') +const { apiErrorHandler } = require("../middleware/error-handler"); // api/admin -router.use('/api/admin', admin) +router.use("/api/admin", admin); // api/users // router.get('/api/users', userController.getUsers) // router.get('/api/signup', userController.signUpPage) -router.post('/api/signup', userController.signUp) +router.post("/api/signup", userController.signUp); // api/tweets -router.get('/api/tweets/:tweet_id', tweetContorller.getTweet) -router.get('/api/tweets', tweetContorller.getTweets) +router.get("/api/tweets/:tweet_id", tweetContorller.getTweet); +router.get("/api/tweets", tweetContorller.getTweets); // router.get("/restaurants", restController.getRestaurants); // router.use("/", (req, res) => res.redirect("/restaurants")); -router.use('/', apiErrorHandler) +// router.use("/", apiErrorHandler); -module.exports = router +module.exports = router; From 4a701739fd3c4bd914be9a1c7321dcf51485315b Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 23 Aug 2023 15:11:35 +0800 Subject: [PATCH 024/170] fix: add engines to package.json --- package.json | 3 +++ routes/index.js | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index fa79350203..71dab2556b 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,9 @@ "lint": "eslint \"**/*.js\" --fix", "test": "mocha test --exit --recursive --timeout 5000" }, + "engines": { + "node": "18.15.0" + }, "author": "", "license": "ISC", "dependencies": { diff --git a/routes/index.js b/routes/index.js index 2c3fcc38f7..0b0501c263 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,28 +1,28 @@ -const express = require("express"); -const router = express.Router(); +const express = require('express') +const router = express.Router() -const admin = require("./modules/admin"); +const admin = require('./modules/admin') -const userController = require("../controllers/apis/user-controller"); -const tweetContorller = require("../controllers/apis/tweet-controller"); +const userController = require('../controllers/apis/user-controller') +const tweetContorller = require('../controllers/apis/tweet-controller') -const { apiErrorHandler } = require("../middleware/error-handler"); +const { apiErrorHandler } = require('../middleware/error-handler') // api/admin -router.use("/api/admin", admin); +router.use('/api/admin', admin) // api/users // router.get('/api/users', userController.getUsers) // router.get('/api/signup', userController.signUpPage) -router.post("/api/signup", userController.signUp); +router.post('/api/signup', userController.signUp) // api/tweets -router.get("/api/tweets/:tweet_id", tweetContorller.getTweet); -router.get("/api/tweets", tweetContorller.getTweets); +router.get('/api/tweets/:tweet_id', tweetContorller.getTweet) +router.get('/api/tweets', tweetContorller.getTweets) // router.get("/restaurants", restController.getRestaurants); // router.use("/", (req, res) => res.redirect("/restaurants")); -// router.use("/", apiErrorHandler); +router.use('/', apiErrorHandler) -module.exports = router; +module.exports = router From 3cf76d45e4ba1a898a97578bb0ed77c4b49f54e1 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 23 Aug 2023 21:41:05 +0800 Subject: [PATCH 025/170] feat: add jwt to admin login --- app.js | 10 +++--- config/passport.js | 18 +++++++++- middleware/api-auth.js | 12 +++++++ package-lock.json | 81 +++++++++++++++++++++++++++++++++++++----- package.json | 2 +- routes/index.js | 3 +- 6 files changed, 109 insertions(+), 17 deletions(-) diff --git a/app.js b/app.js index 48e6ed562f..44ddb481de 100644 --- a/app.js +++ b/app.js @@ -1,13 +1,13 @@ -// if (process.NODE_ENV !== 'production') { -// require('dotenv').config() -// } -require('dotenv').config() +if (process.NODE_ENV !== 'production') { + require('dotenv').config() +} +// require('dotenv').config() const express = require('express') const helpers = require('./_helpers') const bodyParser = require('body-parser') const session = require('express-session') const routes = require('./routes') -const passport = require('./config/passport') // 增加這行,引入 Passport +const passport = require('./config/passport') const app = express() diff --git a/config/passport.js b/config/passport.js index 56a530d50e..30f073bd04 100644 --- a/config/passport.js +++ b/config/passport.js @@ -2,7 +2,10 @@ const passport = require('passport') const LocalStrategy = require('passport-local') const bcrypt = require('bcryptjs') const db = require('../models') -const User = db.User +const { User, Tweet, Reply } = db +const passportJWT = require('passport-jwt') +const JWTStrategy = passportJWT.Strategy +const ExtractJWT = passportJWT.ExtractJwt passport.use( new LocalStrategy( // customize user field @@ -35,4 +38,17 @@ passport.deserializeUser(async (id, cb) => { const user = await User.findByPk(id) return cb(null, user.toJSON()) }) + +// jwt +const jwtOptions = { + jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), + secretOrKey: process.env.JWT_SECRET +} +passport.use( + new JWTStrategy(jwtOptions, (jwtPayload, cb) => { + User.findByPk(jwtPayload.id) + .then(user => cb(null, user)) + .catch(err => cb(err)) + }) +) module.exports = passport diff --git a/middleware/api-auth.js b/middleware/api-auth.js index e69de29bb2..706a9cf80c 100644 --- a/middleware/api-auth.js +++ b/middleware/api-auth.js @@ -0,0 +1,12 @@ +const passport = require('../config/passport') +const authenticated = passport.authenticate('jwt', { session: false }) +const authenticatedAdmin = (req, res, next) => { + if (req.user && req.user.role === 'admin') return next() + return res + .status(403) + .json({ status: 'error', message: 'permission denied' }) +} +module.exports = { + authenticated, + authenticatedAdmin +} diff --git a/package-lock.json b/package-lock.json index d686b25bc1..7a6d660821 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "mocha": "^6.0.2", "mysql2": "^2.3.0", "passport": "^0.4.0", - "passport-jwt": "^4.0.0", + "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", "sequelize": "^6.6.5", "sequelize-cli": "^6.2.0", @@ -38,6 +38,9 @@ "sequelize-test-helpers": "^1.4.2", "standard": "*", "supertest": "^3.3.0" + }, + "engines": { + "node": "18.15.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -4459,14 +4462,48 @@ } }, "node_modules/passport-jwt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", - "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", "dependencies": { - "jsonwebtoken": "^8.2.0", + "jsonwebtoken": "^9.0.0", "passport-strategy": "^1.0.0" } }, + "node_modules/passport-jwt/node_modules/jsonwebtoken": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/passport-jwt/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/passport-jwt/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/passport-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", @@ -9503,12 +9540,38 @@ } }, "passport-jwt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", - "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", + "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", "requires": { - "jsonwebtoken": "^8.2.0", + "jsonwebtoken": "^9.0.0", "passport-strategy": "^1.0.0" + }, + "dependencies": { + "jsonwebtoken": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", + "requires": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + } } }, "passport-local": { diff --git a/package.json b/package.json index 71dab2556b..4d0cc2f4fa 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "mocha": "^6.0.2", "mysql2": "^2.3.0", "passport": "^0.4.0", - "passport-jwt": "^4.0.0", + "passport-jwt": "^4.0.1", "passport-local": "^1.0.0", "sequelize": "^6.6.5", "sequelize-cli": "^6.2.0", diff --git a/routes/index.js b/routes/index.js index 0b0501c263..a53395340c 100644 --- a/routes/index.js +++ b/routes/index.js @@ -7,9 +7,10 @@ const userController = require('../controllers/apis/user-controller') const tweetContorller = require('../controllers/apis/tweet-controller') const { apiErrorHandler } = require('../middleware/error-handler') +const { authenticated, authenticatedAdmin } = require('../middleware/api-auth') // api/admin -router.use('/api/admin', admin) +router.use('/api/admin', authenticated, authenticatedAdmin, admin) // api/users // router.get('/api/users', userController.getUsers) From c5b2a40948e9abfb5bbf7c7f640e098ea2f2aab2 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Wed, 23 Aug 2023 21:58:53 +0800 Subject: [PATCH 026/170] feat: add getUser --- controllers/apis/user-controller.js | 13 +++++++++++++ package-lock.json | 1 + package.json | 1 + routes/index.js | 1 + 4 files changed, 16 insertions(+) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index c5893a52a1..be28a229f3 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,6 +1,7 @@ const bcrypt = require('bcryptjs') const db = require('../../models') const { User } = db + const userController = { signUp: (req, res) => { // 待完成 @@ -17,6 +18,18 @@ const userController = { .then(() => { res.redirect('api/users/signin') }) + }, + getUser: async (req, res, next) => { + try { + const user = await User.findByPk(req.params.id) + if (!user) throw new Error('This user does not exist') + + const userData = user.toJSON() + + res.status(200).json(userData) + } catch (err) { + next(err) + } } } module.exports = userController diff --git a/package-lock.json b/package-lock.json index 0cf04ccedd..0aec804644 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "chai": "^4.2.0", "connect-flash": "^0.1.1", "cors": "^2.8.5", + "dotenv": "^16.3.1", "express": "^4.16.4", "express-session": "^1.17.3", "faker": "^5.5.3", diff --git a/package.json b/package.json index dc7be88540..d3b46bbb64 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "chai": "^4.2.0", "connect-flash": "^0.1.1", "cors": "^2.8.5", + "dotenv": "^16.3.1", "express": "^4.16.4", "express-session": "^1.17.3", "faker": "^5.5.3", diff --git a/routes/index.js b/routes/index.js index 0b0501c263..30cdb425a6 100644 --- a/routes/index.js +++ b/routes/index.js @@ -15,6 +15,7 @@ router.use('/api/admin', admin) // router.get('/api/users', userController.getUsers) // router.get('/api/signup', userController.signUpPage) router.post('/api/signup', userController.signUp) +router.get('/api/users/:id', userController.getUser) // api/tweets router.get('/api/tweets/:tweet_id', tweetContorller.getTweet) From a4bbced4331e82a78ade93628f9d71080c9186db Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 00:00:38 +0800 Subject: [PATCH 027/170] feat: api-auth --- middleware/api-auth.js | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/middleware/api-auth.js b/middleware/api-auth.js index d0733b3a24..bdae697ba8 100644 --- a/middleware/api-auth.js +++ b/middleware/api-auth.js @@ -1,37 +1,3 @@ -// const passport = require('../config/passport') -// const helpers = require('../_helpers') - -// const authenticated = (req, res, next) => { -// passport.authenticate('jwt', { session: false }, (err, user) => { -// if (err) return res.status(401).json({ status: 'error', message: 'error!' }) - -// if (!user) return res.status(403).json({ status: 'error', message: 'user permission denied!' }) -// req.user = user -// console.log(user) -// return next() -// })(req, res, next) -// } - -// const authenticatedAdmin = (req, res, next) => { -// if (helpers.getUser(req) && helpers.getUser(req).role === 'admin') return next() -// return res -// .status(403) -// .json({ status: 'error', message: 'admin permission denied' }) -// } - -// const authenticatedUser = (req, res, next) => { -// if (helpers.getUser(req) && helpers.getUser(req).role === 'user') return next() -// return res -// .status(403) -// .json({ status: 'error', message: 'user permission denied' }) -// } - -// module.exports = { -// authenticated, -// authenticatedAdmin, -// authenticatedUser -// } - const passport = require('../config/passport') const helpers = require('../_helpers') From d6af68c570c1a288c878ef11953965a6259405ff Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 02:59:21 +0800 Subject: [PATCH 028/170] feat: add user signin and signup --- controllers/apis/user-controller.js | 86 ++++++++++++++++++++++++----- middleware/api-auth.js | 22 ++++---- routes/index.js | 10 ++-- 3 files changed, 88 insertions(+), 30 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index be28a229f3..2181da68e7 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,29 +1,87 @@ const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') const db = require('../../models') const { User } = db +const { Op } = require('sequelize') const userController = { - signUp: (req, res) => { - // 待完成 - bcrypt - .hash(req.body.password, 10) - .then(hash => - User.create({ - account: req.body.account, - name: req.body.name, - email: req.body.email, - password: hash - }) + signUp: async (req, res, next) => { + try { + const { account, name, email, password, checkPassword } = req.body + + if (!account || !name || !email || !password || !checkPassword) throw new Error('all the blanks are required') + + // 檢查帳號是否重複 + const user = await User.findOne( + { + where: { + [Op.or]: [ + { email }, + { account } + ] + } + } ) - .then(() => { - res.redirect('api/users/signin') + + if (user) { + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') + } + + const createdUser = await User.create({ + name, + email, + account, + password: bcrypt.hashSync(password, 10), + avatar: 'https://picsum.photos/100/100', + cover: 'https://picsum.photos/id/237/700/400', + role: 'user', + createdAt: new Date(), + updatedAt: new Date() + }) + + res.status(200).json({ + status: 'success', + message: 'Successfully create user.', + data: createdUser + }) + } catch (err) { + next(err) + } + }, + signIn: async (req, res, next) => { + try { + const { account, password } = req.body + if (!account || !password) throw new Error('Please enter account and password') + + const user = await User.findOne({ where: { account } }) + if (!user) throw new Error('User does not exist') + if (user.role === 'admin') throw new Error('admin permission denied') + if (!bcrypt.compareSync(password, user.password)) throw new Error('Incorrect password') + const payload = { + id: user.id, + account: user.account, + role: user.role + } + const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' }) + const userData = user.toJSON() + + res.json({ + status: 'success', + data: { + token, + user: userData + } }) + } catch (err) { + next(err) + } }, getUser: async (req, res, next) => { try { const user = await User.findByPk(req.params.id) if (!user) throw new Error('This user does not exist') - + delete user.password const userData = user.toJSON() res.status(200).json(userData) diff --git a/middleware/api-auth.js b/middleware/api-auth.js index bdae697ba8..737a9a58a8 100644 --- a/middleware/api-auth.js +++ b/middleware/api-auth.js @@ -3,15 +3,9 @@ const helpers = require('../_helpers') const authenticated = (req, res, next) => { passport.authenticate('jwt', { session: false }, (err, user) => { + if (err || !user) return res.status(401).json({ status: 'error', message: 'unauthorized' }) req.user = user - - if (err) return res.status(401).json({ status: 'error', message: 'error!' }) - - if (!user) return res.status(401).json({ status: 'error', message: 'unauthorized!' }) - - console.log(req.user) - - return next() + next() })(req, res, next) } @@ -19,9 +13,17 @@ const authenticatedAdmin = (req, res, next) => { if (helpers.getUser(req) && helpers.getUser(req).role === 'admin') return next() return res .status(403) - .json({ status: 'error', message: 'permission denied' }) + .json({ status: 'error', message: 'admin permission denied' }) } + +const authenticatedUser = (req, res, next) => { + console.log(req.user.toJSON()) + if (helpers.getUser(req).role === 'user') return next() + return res.status(403).json({ status: 'error', message: 'user permission denied' }) +} + module.exports = { authenticated, - authenticatedAdmin + authenticatedAdmin, + authenticatedUser } diff --git a/routes/index.js b/routes/index.js index f18b2ac7d4..58a514e194 100644 --- a/routes/index.js +++ b/routes/index.js @@ -7,23 +7,21 @@ const userController = require('../controllers/apis/user-controller') const tweetContorller = require('../controllers/apis/tweet-controller') const { apiErrorHandler } = require('../middleware/error-handler') -const { authenticated, authenticatedAdmin } = require('../middleware/api-auth') +const { authenticated, authenticatedAdmin, authenticatedUser } = require('../middleware/api-auth') // api/admin router.use('/api/admin', authenticated, authenticatedAdmin, admin) // api/users // router.get('/api/users', userController.getUsers) -// router.get('/api/signup', userController.signUpPage) -router.post('/api/signup', userController.signUp) -router.get('/api/users/:id', userController.getUser) +router.post('/api/users', userController.signUp) +router.post('/api/users/signin', userController.signIn) +router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) // api/tweets router.get('/api/tweets/:tweet_id', tweetContorller.getTweet) router.get('/api/tweets', tweetContorller.getTweets) -// router.get("/restaurants", restController.getRestaurants); -// router.use("/", (req, res) => res.redirect("/restaurants")); router.use('/', apiErrorHandler) From 0d708dae5157357736ba263684daa8fd8f906383 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 24 Aug 2023 10:48:50 +0800 Subject: [PATCH 029/170] fix: seeder tweets --- seeders/20230821074916-tweets-seed-file.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index f97863ecf3..f6ec202cf1 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -1,9 +1,16 @@ 'use strict' const faker = require('faker') +const db = require('../models') +const User = db.User module.exports = { up: async (queryInterface, Sequelize) => { const data = [] + const userData = await User.findAll({ + raw: true, + nest: true, + attributes: ['id'] + }) // eslint-disable-next-line array-callback-return Array.from({ length: 10 }).map((user, i) => { for (let j = 0; j < 10; ++j) { @@ -12,7 +19,7 @@ module.exports = { description: faker.lorem.text(140), created_at: new Date(), updated_at: new Date(), - User_id: i + 1 + User_id: userData[i].id }) } }) From 40e26b37ce6f2e2d136663099d497ed8632faf87 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 10:51:52 +0800 Subject: [PATCH 030/170] feat: add getUserReplies --- controllers/apis/user-controller.js | 26 +++++++++++++++++++++- models/reply.js | 4 ++-- models/tweet.js | 2 +- routes/index.js | 1 + seeders/20230821074916-tweets-seed-file.js | 26 ++++++++++++++-------- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index be28a229f3..265b72d6e7 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,6 +1,6 @@ const bcrypt = require('bcryptjs') const db = require('../../models') -const { User } = db +const { User, Tweet, Reply } = db const userController = { signUp: (req, res) => { @@ -30,6 +30,30 @@ const userController = { } catch (err) { next(err) } + }, + getUserReplies: async (req, res, next) => { + try { + const userId = req.params.id + const replies = await Reply.findAll({ + where: { UserId: userId }, + include: [ + { model: User, as: 'userreply', attributes: { exclude: ['password'] } }, + { + model: Tweet, + as: 'usertweets', + include: [{ model: User, as: 'author', attributes: ['account'] }] + } + ], + order: [['createdAt', 'DESC']], + nest: true + }) + + const userRepliesResult = replies.map(reply => reply.toJSON()) + res.status(200).json(userRepliesResult) + } catch (err) { + next(err) + } } } + module.exports = userController diff --git a/models/reply.js b/models/reply.js index 6fd0fef860..c70460a11e 100644 --- a/models/reply.js +++ b/models/reply.js @@ -11,8 +11,8 @@ module.exports = (sequelize, DataTypes) => { */ static associate (models) { // define association here - Reply.belongsTo(models.User, { foreignKey: 'userId' }) - Reply.belongsTo(models.Tweet, { foreignKey: 'tweetId' }) + Reply.belongsTo(models.User, { foreignKey: 'userId', as: 'userreply' }) + Reply.belongsTo(models.Tweet, { foreignKey: 'tweetId', as: 'usertweets' }) } }; Reply.init({ diff --git a/models/tweet.js b/models/tweet.js index 3aafa8a15f..2938d906d3 100644 --- a/models/tweet.js +++ b/models/tweet.js @@ -9,7 +9,7 @@ module.exports = (sequelize, DataTypes) => { */ static associate (models) { // define association here - Tweet.hasMany(models.Reply, { foreignKey: 'tweetId' }) + Tweet.hasMany(models.Reply, { foreignKey: 'tweetId', as: 'replies' }) Tweet.hasMany(models.Like, { foreignKey: 'tweetId' }) Tweet.belongsTo(models.User, { foreignKey: 'userId', as: 'author' }) } diff --git a/routes/index.js b/routes/index.js index f18b2ac7d4..aa0a7b0856 100644 --- a/routes/index.js +++ b/routes/index.js @@ -17,6 +17,7 @@ router.use('/api/admin', authenticated, authenticatedAdmin, admin) // router.get('/api/signup', userController.signUpPage) router.post('/api/signup', userController.signUp) router.get('/api/users/:id', userController.getUser) +router.get('/api/users/:id/replied_tweets', userController.getUserReplies) // api/tweets router.get('/api/tweets/:tweet_id', tweetContorller.getTweet) diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index f97863ecf3..e36b36cde6 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -3,20 +3,28 @@ const faker = require('faker') module.exports = { up: async (queryInterface, Sequelize) => { + const users = await queryInterface.sequelize.query( + 'SELECT id FROM Users WHERE role = "user";', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + const data = [] - // eslint-disable-next-line array-callback-return - Array.from({ length: 10 }).map((user, i) => { - for (let j = 0; j < 10; ++j) { + const Textmax = 140 + + for (let i = 0; i < users.length; i++) { + const user = users[i] + + for (let j = 0; j < 10; j++) { data.push({ - id: j * 10 + i + 1, - description: faker.lorem.text(140), + User_id: user.id, + description: faker.lorem.text(Textmax), created_at: new Date(), - updated_at: new Date(), - User_id: i + 1 + updated_at: new Date() }) } - }) - await queryInterface.bulkInsert('Tweets', data, {}) + } + + await queryInterface.bulkInsert('Tweets', data) }, down: async (queryInterface, Sequelize) => { From 2ee5f28abdbb051098a7447da3e882d900abd5e9 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 24 Aug 2023 11:31:04 +0800 Subject: [PATCH 031/170] fix: bugs --- app.js | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/app.js b/app.js index 44ddb481de..2f71d7cab8 100644 --- a/app.js +++ b/app.js @@ -1,33 +1,33 @@ -if (process.NODE_ENV !== 'production') { - require('dotenv').config() -} -// require('dotenv').config() -const express = require('express') -const helpers = require('./_helpers') -const bodyParser = require('body-parser') -const session = require('express-session') -const routes = require('./routes') -const passport = require('./config/passport') +// if (process.NODE_ENV !== 'production') { +// require('dotenv').config() +// } +require("dotenv").config(); +const express = require("express"); +const helpers = require("./_helpers"); +const bodyParser = require("body-parser"); +const session = require("express-session"); +const routes = require("./routes"); +const passport = require("./config/passport"); -const app = express() +const app = express(); // bodyparser設定 -app.use(bodyParser.urlencoded({ extended: true })) -app.use(bodyParser.json()) +app.use(bodyParser.urlencoded({ extended: true })); +app.use(bodyParser.json()); // passport 初始化 -app.use(passport.initialize()) -app.use(passport.session()) +app.use(passport.initialize()); +app.use(passport.session()); -const port = process.env.PORT || 3000 +const port = process.env.PORT || 3000; // use helpers.getUser(req) to replace req.user -function authenticated (req, res, next) { +function authenticated(req, res, next) { // passport.authenticate('jwt', { ses... } -app.use(routes) +app.use(routes); -app.get('/', (req, res) => res.send('Hello World!')) -app.listen(port, () => console.log(`Example app listening on port ${port}!`)) +app.get("/", (req, res) => res.send("Hello World!")); +app.listen(port, () => console.log(`Example app listening on port ${port}!`)); -module.exports = app +module.exports = app; From e09dd2f76f2434d3a71368fb8e3b198708d942e5 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 24 Aug 2023 12:11:38 +0800 Subject: [PATCH 032/170] fix: bugs tweet seeder --- app.js | 36 +++++++++++----------- seeders/20230821074916-tweets-seed-file.js | 10 ++---- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/app.js b/app.js index 3e5997daf0..feaa47991a 100644 --- a/app.js +++ b/app.js @@ -1,33 +1,33 @@ // if (process.NODE_ENV !== "production") { // require("dotenv").config(); // } -require("dotenv").config(); -const express = require("express"); -const helpers = require("./_helpers"); -const bodyParser = require("body-parser"); -const session = require("express-session"); -const routes = require("./routes"); -const passport = require("./config/passport"); +require('dotenv').config() +const express = require('express') +const helpers = require('./_helpers') +const bodyParser = require('body-parser') +const session = require('express-session') +const routes = require('./routes') +const passport = require('./config/passport') -const app = express(); +const app = express() // bodyparser設定 -app.use(bodyParser.urlencoded({ extended: true })); -app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })) +app.use(bodyParser.json()) // passport 初始化 -app.use(passport.initialize()); -app.use(passport.session()); +app.use(passport.initialize()) +app.use(passport.session()) -const port = process.env.PORT || 3000; +const port = process.env.PORT || 3000 // use helpers.getUser(req) to replace req.user -function authenticated(req, res, next) { +function authenticated (req, res, next) { // passport.authenticate('jwt', { ses... } -app.use(routes); +app.use(routes) -app.get("/", (req, res) => res.send("Hello World!")); -app.listen(port, () => console.log(`Example app listening on port ${port}!`)); +app.get('/', (req, res) => res.send('Hello World!')) +app.listen(port, () => console.log(`Example app listening on port ${port}!`)) -module.exports = app; +module.exports = app diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index 131a45b712..a6e28e14f8 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -5,11 +5,6 @@ const User = db.User module.exports = { up: async (queryInterface, Sequelize) => { - const users = await queryInterface.sequelize.query( - 'SELECT id FROM Users WHERE role = "user";', - { type: queryInterface.sequelize.QueryTypes.SELECT } - ) - const data = [] const userData = await User.findAll({ raw: true, @@ -20,14 +15,13 @@ module.exports = { Array.from({ length: 10 }).map((user, i) => { for (let j = 0; j < 10; ++j) { data.push({ - User_id: user.id, - description: faker.lorem.text(Textmax), + description: faker.lorem.text(140), created_at: new Date(), updated_at: new Date(), User_id: userData[i].id }) } - } + }) await queryInterface.bulkInsert('Tweets', data) }, From 8fa4ee314c3e0f3dd9854df8315b6d676227a49a Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 24 Aug 2023 12:41:16 +0800 Subject: [PATCH 033/170] fix: modify app.js --- app.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/app.js b/app.js index feaa47991a..6e7d27a078 100644 --- a/app.js +++ b/app.js @@ -1,33 +1,33 @@ // if (process.NODE_ENV !== "production") { // require("dotenv").config(); // } -require('dotenv').config() -const express = require('express') -const helpers = require('./_helpers') -const bodyParser = require('body-parser') -const session = require('express-session') -const routes = require('./routes') -const passport = require('./config/passport') +// require('dotenv').config() +const express = require("express"); +const helpers = require("./_helpers"); +const bodyParser = require("body-parser"); +const session = require("express-session"); +const routes = require("./routes"); +const passport = require("./config/passport"); -const app = express() +const app = express(); // bodyparser設定 -app.use(bodyParser.urlencoded({ extended: true })) -app.use(bodyParser.json()) +app.use(bodyParser.urlencoded({ extended: true })); +app.use(bodyParser.json()); // passport 初始化 -app.use(passport.initialize()) -app.use(passport.session()) +app.use(passport.initialize()); +app.use(passport.session()); -const port = process.env.PORT || 3000 +const port = process.env.PORT || 3000; // use helpers.getUser(req) to replace req.user -function authenticated (req, res, next) { +function authenticated(req, res, next) { // passport.authenticate('jwt', { ses... } -app.use(routes) +app.use(routes); -app.get('/', (req, res) => res.send('Hello World!')) -app.listen(port, () => console.log(`Example app listening on port ${port}!`)) +app.get("/", (req, res) => res.send("Hello World!")); +app.listen(port, () => console.log(`Example app listening on port ${port}!`)); -module.exports = app +module.exports = app; From 38f1489367d12bb3330efcb3947449243b66c8d7 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 24 Aug 2023 12:45:44 +0800 Subject: [PATCH 034/170] fix: add require dotenv --- app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 6e7d27a078..42acf4c0a0 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,6 @@ -// if (process.NODE_ENV !== "production") { -// require("dotenv").config(); -// } +if (process.NODE_ENV !== "production") { + require("dotenv").config(); +} // require('dotenv').config() const express = require("express"); const helpers = require("./_helpers"); From 4ad76678ee651f5cba71f7cff9c2afb8665a7217 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 24 Aug 2023 12:50:11 +0800 Subject: [PATCH 035/170] fix: modify package.json --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index eacb0f66a4..cc06fae7e7 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "sinon-chai": "^3.3.0" }, "devDependencies": { - "dotenv": "^16.3.1", "eslint-config-standard": "^17.1.0", "proxyquire": "^2.1.3", "sequelize-test-helpers": "^1.4.2", From 5dd43b9311ab45c767d94a1bbf1de699e329b02c Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 24 Aug 2023 16:07:57 +0800 Subject: [PATCH 036/170] feat: jwt --- config/passport.js | 49 +++++++--------------------- controllers/apis/admin-controller.js | 2 +- models/followship.js | 27 +++++++-------- models/reply.js | 32 ++++++++++-------- models/user.js | 9 ++++- routes/index.js | 1 + routes/modules/admin.js | 2 +- 7 files changed, 54 insertions(+), 68 deletions(-) diff --git a/config/passport.js b/config/passport.js index 30f073bd04..9fe48b493e 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,53 +1,26 @@ const passport = require('passport') -const LocalStrategy = require('passport-local') -const bcrypt = require('bcryptjs') const db = require('../models') -const { User, Tweet, Reply } = db +const { User, Tweet, Reply, Followship } = db const passportJWT = require('passport-jwt') const JWTStrategy = passportJWT.Strategy const ExtractJWT = passportJWT.ExtractJwt -passport.use( - new LocalStrategy( - // customize user field - { - usernameField: 'account', - passwordField: 'password', - passReqToCallback: false - }, - // authenticate user - (account, password, cb) => { - User.findOne({ where: { account } }).then(user => { - if (!user) { - return cb(null, false, { message: '帳號或密碼輸入錯誤!' }) - } - bcrypt.compare(password, user.password).then(res => { - if (!res) { - return cb(null, false, { message: '帳號或密碼輸入錯誤!' }) - } - return cb(null, user) - }) - }) - } - ) -) -// serialize and deserialize user -passport.serializeUser((user, cb) => { - cb(null, user.id) -}) -passport.deserializeUser(async (id, cb) => { - const user = await User.findByPk(id) - return cb(null, user.toJSON()) -}) -// jwt const jwtOptions = { jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), secretOrKey: process.env.JWT_SECRET } passport.use( new JWTStrategy(jwtOptions, (jwtPayload, cb) => { - User.findByPk(jwtPayload.id) - .then(user => cb(null, user)) + User.findByPk(jwtPayload.id, { + include: [ + { model: User, as: 'Followings' }, + { model: User, as: 'Followers' } + ] + }) + .then(user => { + if (!user) return cb(null, false) + cb(null, user.toJSON()) + }) .catch(err => cb(err)) }) ) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 5f829fe905..b3b3ecbfff 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -98,7 +98,7 @@ const adminController = { // Admin 登入 signIn: (req, res, next) => { try { - const userData = req.user.toJSON() + const userData = req.user const token = jwt.sign(userData, process.env.JWT_SECRET, { expiresIn: '30d' }) diff --git a/models/followship.js b/models/followship.js index 1ab09e1b89..97bf78a757 100644 --- a/models/followship.js +++ b/models/followship.js @@ -1,7 +1,5 @@ 'use strict' -const { - Model -} = require('sequelize') +const { Model } = require('sequelize') module.exports = (sequelize, DataTypes) => { class Followship extends Model { /** @@ -12,15 +10,18 @@ module.exports = (sequelize, DataTypes) => { static associate (models) { // define association here } - }; - Followship.init({ - followerId: DataTypes.INTEGER, - followingId: DataTypes.INTEGER - }, { - sequelize, - modelName: 'Followship', - tableName: 'Followships', - underscored: true - }) + } + Followship.init( + { + followerId: DataTypes.INTEGER, + followingId: DataTypes.INTEGER + }, + { + sequelize, + modelName: 'Followship', + tableName: 'Followships', + underscored: true + } + ) return Followship } diff --git a/models/reply.js b/models/reply.js index 6fd0fef860..b17b14329d 100644 --- a/models/reply.js +++ b/models/reply.js @@ -1,7 +1,5 @@ 'use strict' -const { - Model -} = require('sequelize') +const { Model } = require('sequelize') module.exports = (sequelize, DataTypes) => { class Reply extends Model { /** @@ -13,17 +11,23 @@ module.exports = (sequelize, DataTypes) => { // define association here Reply.belongsTo(models.User, { foreignKey: 'userId' }) Reply.belongsTo(models.Tweet, { foreignKey: 'tweetId' }) + Reply.belongsTo(models.User, { foreignKey: 'userId', as: 'replier' }) + + // Reply.hasMany(models.User, { foreignKey: "userId", as: "likedReplies" }); } - }; - Reply.init({ - comment: DataTypes.TEXT, - UserId: DataTypes.INTEGER, - TweetId: DataTypes.INTEGER - }, { - sequelize, - modelName: 'Reply', - tableName: 'Replies', - underscored: true - }) + } + Reply.init( + { + comment: DataTypes.TEXT, + UserId: DataTypes.INTEGER, + TweetId: DataTypes.INTEGER + }, + { + sequelize, + modelName: 'Reply', + tableName: 'Replies', + underscored: true + } + ) return Reply } diff --git a/models/user.js b/models/user.js index 09d455ab14..7d6895e306 100644 --- a/models/user.js +++ b/models/user.js @@ -10,7 +10,14 @@ module.exports = (sequelize, DataTypes) => { static associate (models) { // define association here User.hasMany(models.Tweet, { foreignKey: 'userId', as: 'author' }) - User.hasMany(models.Reply, { foreignKey: 'userId' }) + User.hasMany(models.Reply, { foreignKey: 'userId', as: 'replier' }) + + // User.belongsTo(models.Tweet, { foreignKey: "userId", as: "likedTweets" }); + // User.belongsTo(models.Tweet, { + // foreignKey: "userId", + // as: "likedReplies", + // }); + User.hasMany(models.Like, { foreignKey: 'userId' }) User.belongsToMany(models.User, { through: models.Followship, diff --git a/routes/index.js b/routes/index.js index a53395340c..1fa43d0064 100644 --- a/routes/index.js +++ b/routes/index.js @@ -11,6 +11,7 @@ const { authenticated, authenticatedAdmin } = require('../middleware/api-auth') // api/admin router.use('/api/admin', authenticated, authenticatedAdmin, admin) +// router.use("/api/admin", admin); // api/users // router.get('/api/users', userController.getUsers) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index e384997d77..10bd39f51f 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -5,7 +5,7 @@ const passport = require('passport') router.post( '/login', - passport.authenticate('local', { session: false }), + passport.authenticate('jwt', { session: false }), adminController.signIn ) router.get('/users', adminController.getUsers) From 6263c17ccdd43cc7b88668011d6df5be2a2140e0 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 16:39:07 +0800 Subject: [PATCH 037/170] bug: still cannot pass test --- app.js | 8 +- controllers/apis/user-controller.js | 95 +++++++++++++++++----- seeders/20230821074916-tweets-seed-file.js | 29 ++++--- 3 files changed, 94 insertions(+), 38 deletions(-) diff --git a/app.js b/app.js index 9ec59c23f5..3fef6b1bf1 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,7 @@ -if (process.env.NODE_ENV !== 'production') { - require('dotenv').config() -} -// require('dotenv').config() +// if (process.env.NODE_ENV !== 'production') { +// require('dotenv').config() +// } +require('dotenv').config() const express = require('express') const cors = require('cors') const helpers = require('./_helpers') diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 9051a5aabd..3725933a2b 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,9 +1,11 @@ const bcrypt = require('bcryptjs') const jwt = require('jsonwebtoken') const db = require('../../models') +const { getUser } = require('../../_helpers') -const { User, Tweet, Reply } = db +const { User, Tweet, Reply, Followship } = db const { Op } = require('sequelize') +const sequelize = require('sequelize') const userController = { signUp: async (req, res, next) => { @@ -80,12 +82,43 @@ const userController = { }, getUser: async (req, res, next) => { try { - const user = await User.findByPk(req.params.id) - if (!user) throw new Error('This user does not exist') + const { id } = req.params + const currentUserId = getUser(req).dataValues.id + console.log(currentUserId) + + const [user, tweetCount, followerCount, followingCount] = await Promise.all([ + User.findByPk(id, { raw: true, nest: true }), + Tweet.count({ + where: { UserId: id } + }), + Followship.count({ + where: { followerId: id } + }), + Followship.count({ + where: { followingId: id } + }) + ]) + + if (!user) res.status(401).json({ status: 'error', message: 'This user does not exist' }) + delete user.password - const userData = user.toJSON() + user.tweetCount = tweetCount + user.followerCount = followerCount + user.followingCount = followingCount + + if (Number(id) !== currentUserId) { + const checkUserFollowing = await Followship.findAll({ + where: { followerId: currentUserId }, + raw: true + }) + user.isFollowed = checkUserFollowing.some(follow => follow.followingId === Number(id)) + } + + if (Number(id) === currentUserId) res.status(400).json({ status: 'error', message: '使用者無法追蹤自己!' }) - res.status(200).json(userData) + // console.log(user) + + res.status(200).json(user) } catch (err) { next(err) } @@ -93,21 +126,45 @@ const userController = { getUserReplies: async (req, res, next) => { try { const userId = req.params.id - const replies = await Reply.findAll({ - where: { UserId: userId }, - include: [ - { model: User, as: 'userreply', attributes: { exclude: ['password'] } }, - { - model: Tweet, - as: 'usertweets', - include: [{ model: User, as: 'author', attributes: ['account'] }] - } - ], - order: [['createdAt', 'DESC']], - nest: true - }) - const userRepliesResult = replies.map(reply => reply.toJSON()) + const [user, replies] = await Promise.all([ + User.findByPk(userId, { raw: true, nest: true }), + Reply.findAll({ + where: { UserId: userId }, + include: [ + { model: User, as: 'userreply', attributes: { exclude: ['password'] } }, + { + model: Tweet, + as: 'usertweets', + include: [{ model: User, as: 'author', attributes: ['account'] }] + } + ], + // attributes: { + // include: [[sequelize.literal('(SELECT name FROM Users WHERE Users.id = Tweet.user_id)'), 'tweetBelongerName'], + // [sequelize.literal('(SELECT account FROM Users WHERE Users.id = Tweet.UserId)'), 'tweetBelongerAccount'] + // ] + // }, + order: [['createdAt', 'DESC']], + nest: true + } + )]) + + console.log(user, replies) + const userRepliesResult = replies.map(reply => ({ + replyId: reply.id, + comment: reply.comment, + replierId: user.id, + replierName: user.name, + replierAvatar: user.avatar, + replierAccount: user.account, + createdAt: reply.createdAt, + tweetId: reply.TweetId + // tweetBelongerName: reply.tweetBelongerName, + // tweetBelongerAccount: reply.tweetBelongerAccount + })) + + console.log(userRepliesResult) + res.status(200).json(userRepliesResult) } catch (err) { next(err) diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index e36b36cde6..a6e28e14f8 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -1,28 +1,27 @@ 'use strict' const faker = require('faker') +const db = require('../models') +const User = db.User module.exports = { up: async (queryInterface, Sequelize) => { - const users = await queryInterface.sequelize.query( - 'SELECT id FROM Users WHERE role = "user";', - { type: queryInterface.sequelize.QueryTypes.SELECT } - ) - const data = [] - const Textmax = 140 - - for (let i = 0; i < users.length; i++) { - const user = users[i] - - for (let j = 0; j < 10; j++) { + const userData = await User.findAll({ + raw: true, + nest: true, + attributes: ['id'] + }) + // eslint-disable-next-line array-callback-return + Array.from({ length: 10 }).map((user, i) => { + for (let j = 0; j < 10; ++j) { data.push({ - User_id: user.id, - description: faker.lorem.text(Textmax), + description: faker.lorem.text(140), created_at: new Date(), - updated_at: new Date() + updated_at: new Date(), + User_id: userData[i].id }) } - } + }) await queryInterface.bulkInsert('Tweets', data) }, From 2dac519f537baee2ef950bac9099b497769709c1 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 16:41:40 +0800 Subject: [PATCH 038/170] fix: eslint --- app.js | 38 +++++++++++++++++++------------------- models/reply.js | 2 -- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/app.js b/app.js index 42acf4c0a0..44ddb481de 100644 --- a/app.js +++ b/app.js @@ -1,33 +1,33 @@ -if (process.NODE_ENV !== "production") { - require("dotenv").config(); +if (process.NODE_ENV !== 'production') { + require('dotenv').config() } // require('dotenv').config() -const express = require("express"); -const helpers = require("./_helpers"); -const bodyParser = require("body-parser"); -const session = require("express-session"); -const routes = require("./routes"); -const passport = require("./config/passport"); +const express = require('express') +const helpers = require('./_helpers') +const bodyParser = require('body-parser') +const session = require('express-session') +const routes = require('./routes') +const passport = require('./config/passport') -const app = express(); +const app = express() // bodyparser設定 -app.use(bodyParser.urlencoded({ extended: true })); -app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })) +app.use(bodyParser.json()) // passport 初始化 -app.use(passport.initialize()); -app.use(passport.session()); +app.use(passport.initialize()) +app.use(passport.session()) -const port = process.env.PORT || 3000; +const port = process.env.PORT || 3000 // use helpers.getUser(req) to replace req.user -function authenticated(req, res, next) { +function authenticated (req, res, next) { // passport.authenticate('jwt', { ses... } -app.use(routes); +app.use(routes) -app.get("/", (req, res) => res.send("Hello World!")); -app.listen(port, () => console.log(`Example app listening on port ${port}!`)); +app.get('/', (req, res) => res.send('Hello World!')) +app.listen(port, () => console.log(`Example app listening on port ${port}!`)) -module.exports = app; +module.exports = app diff --git a/models/reply.js b/models/reply.js index 42587da8be..b6b5fdca69 100644 --- a/models/reply.js +++ b/models/reply.js @@ -12,8 +12,6 @@ module.exports = (sequelize, DataTypes) => { Reply.belongsTo(models.Tweet, { foreignKey: 'tweetId' }) Reply.belongsTo(models.User, { foreignKey: 'userId', as: 'replier' }) - - } } Reply.init( From 4dfd40e48a7ea8769cbcea0a7ef2921837949ef9 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 20:24:32 +0800 Subject: [PATCH 039/170] fix: pass getUser feature --- _helpers.js | 2 +- controllers/apis/user-controller.js | 6 +----- middleware/api-auth.js | 1 - 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/_helpers.js b/_helpers.js index d83196d1fb..4f17063ab8 100644 --- a/_helpers.js +++ b/_helpers.js @@ -1,5 +1,5 @@ function getUser (req) { - return req.user + return req.user || null } module.exports = { diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 3725933a2b..3156be1c30 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -99,7 +99,7 @@ const userController = { }) ]) - if (!user) res.status(401).json({ status: 'error', message: 'This user does not exist' }) + if (!user) return res.status(401).json({ status: 'error', message: 'This user does not exist' }) delete user.password user.tweetCount = tweetCount @@ -114,10 +114,6 @@ const userController = { user.isFollowed = checkUserFollowing.some(follow => follow.followingId === Number(id)) } - if (Number(id) === currentUserId) res.status(400).json({ status: 'error', message: '使用者無法追蹤自己!' }) - - // console.log(user) - res.status(200).json(user) } catch (err) { next(err) diff --git a/middleware/api-auth.js b/middleware/api-auth.js index 737a9a58a8..f9252d4df8 100644 --- a/middleware/api-auth.js +++ b/middleware/api-auth.js @@ -17,7 +17,6 @@ const authenticatedAdmin = (req, res, next) => { } const authenticatedUser = (req, res, next) => { - console.log(req.user.toJSON()) if (helpers.getUser(req).role === 'user') return next() return res.status(403).json({ status: 'error', message: 'user permission denied' }) } From 8934b2d2f96a5f71341c6572bc8d9cb242fc6d6f Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 20:58:00 +0800 Subject: [PATCH 040/170] fix: getUserReplies --- controllers/apis/user-controller.js | 13 +++++++------ models/reply.js | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 3156be1c30..7e38c012c0 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -128,11 +128,11 @@ const userController = { Reply.findAll({ where: { UserId: userId }, include: [ - { model: User, as: 'userreply', attributes: { exclude: ['password'] } }, + { model: User, as: 'replier', attributes: { exclude: ['password'] } }, { model: Tweet, - as: 'usertweets', - include: [{ model: User, as: 'author', attributes: ['account'] }] + as: 'tweetreply', + include: [{ model: User, as: 'author', attributes: ['account', 'name'] }] } ], // attributes: { @@ -154,15 +154,16 @@ const userController = { replierAvatar: user.avatar, replierAccount: user.account, createdAt: reply.createdAt, - tweetId: reply.TweetId - // tweetBelongerName: reply.tweetBelongerName, - // tweetBelongerAccount: reply.tweetBelongerAccount + tweetId: reply.TweetId, + tweetBelongerName: reply.tweetreply.author.name, + tweetBelongerAccount: reply.tweetreply.author.account })) console.log(userRepliesResult) res.status(200).json(userRepliesResult) } catch (err) { + console.error(err) next(err) } } diff --git a/models/reply.js b/models/reply.js index b6b5fdca69..1aa4851932 100644 --- a/models/reply.js +++ b/models/reply.js @@ -10,7 +10,7 @@ module.exports = (sequelize, DataTypes) => { static associate (models) { // define association here - Reply.belongsTo(models.Tweet, { foreignKey: 'tweetId' }) + Reply.belongsTo(models.Tweet, { foreignKey: 'tweetId', as: 'tweetreply' }) Reply.belongsTo(models.User, { foreignKey: 'userId', as: 'replier' }) } } From e963592ae114e2724744c40d5897e05566f6e343 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 22:03:16 +0800 Subject: [PATCH 041/170] fix: admin/getUsers --- controllers/apis/admin-controller.js | 28 +++++++++++++++------ controllers/apis/user-controller.js | 6 ----- seeders/20230821081029-replies-seed-file.js | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index b3b3ecbfff..22116aa16c 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -1,3 +1,4 @@ +const bcrypt = require('bcryptjs') const db = require('../../models') const { User, Tweet, Like } = db // const bcrypt = require('bcrypt-nodejs') @@ -11,13 +12,11 @@ const adminController = { attributes: { exclude: [ 'email', - 'introduction', 'password', 'updatedAt', 'createdAt' ] - }, - where: { role: 'user' } + } } User.findAll(options) .then(users => { @@ -25,6 +24,7 @@ const adminController = { if (user.introduction) { user.introduction = user.introduction.substring(0, 50) } + console.log(user) }) res.status(200).json(users) }) @@ -96,10 +96,23 @@ const adminController = { ) }, // Admin 登入 - signIn: (req, res, next) => { + signIn: async (req, res, next) => { try { - const userData = req.user - const token = jwt.sign(userData, process.env.JWT_SECRET, { + const { account, password } = req.body + if (!account || !password) throw new Error('Please enter account and password') + + const userData = await User.findOne({ where: { account } }) + + if (!userData) throw new Error('User does not exist') + if (userData.role === 'user') throw new Error('user permission denied') + if (!bcrypt.compareSync(password, userData.password)) throw new Error('Incorrect password') + + const payload = { + id: userData.id, + account: userData.account, + role: userData.role + } + const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' }) res.json({ @@ -110,8 +123,7 @@ const adminController = { } }) } catch (err) { - console.log(err.message) - // next(err); + next(err) } } } diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 7e38c012c0..cb8aa62f73 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -5,7 +5,6 @@ const { getUser } = require('../../_helpers') const { User, Tweet, Reply, Followship } = db const { Op } = require('sequelize') -const sequelize = require('sequelize') const userController = { signUp: async (req, res, next) => { @@ -135,11 +134,6 @@ const userController = { include: [{ model: User, as: 'author', attributes: ['account', 'name'] }] } ], - // attributes: { - // include: [[sequelize.literal('(SELECT name FROM Users WHERE Users.id = Tweet.user_id)'), 'tweetBelongerName'], - // [sequelize.literal('(SELECT account FROM Users WHERE Users.id = Tweet.UserId)'), 'tweetBelongerAccount'] - // ] - // }, order: [['createdAt', 'DESC']], nest: true } diff --git a/seeders/20230821081029-replies-seed-file.js b/seeders/20230821081029-replies-seed-file.js index 726069084c..ff65ca0605 100644 --- a/seeders/20230821081029-replies-seed-file.js +++ b/seeders/20230821081029-replies-seed-file.js @@ -8,7 +8,7 @@ module.exports = { const userData = await User.findAll({ raw: true, nest: true, - where: { role: 'user' }, + // where: { role: 'user' }, attributes: ['id'] }) const tweetData = await Tweet.findAll({ From 73e5f2ef08afd6f91812481246a5802985f061fd Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 22:23:30 +0800 Subject: [PATCH 042/170] refactor: getTweets and getTweet controller --- controllers/apis/tweet-controller.js | 30 +++++++++++++++------------- routes/index.js | 4 ++-- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 82275ba3b5..77d7f14735 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,23 +1,25 @@ const { Tweet } = require('../../models') const tweetContorller = { - getTweets: (req, res, next) => { - return Tweet.findAll({ - raw: true - }) - .then(tweets => { - res.json(tweets) + getTweets: async (req, res, next) => { + try { + const tweets = await Tweet.findAll({ + raw: true }) - .catch(err => next(err)) + res.json(tweets) + } catch (err) { + next(err) + } }, - getTweet: (req, res, next) => { - const TweetId = req.params.tweet_id + getTweet: async (req, res, next) => { + try { + const tweetId = req.params.tweet_id - return Tweet.findByPk(TweetId) - .then(tweet => { - res.json(tweet) - }) - .catch(err => next(err)) + const tweet = await Tweet.findByPk(tweetId) + res.json(tweet) + } catch (err) { + next(err) + } } } diff --git a/routes/index.js b/routes/index.js index 8d143c8865..036ca1fe83 100644 --- a/routes/index.js +++ b/routes/index.js @@ -21,8 +21,8 @@ router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, us router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) // api/tweets -router.get('/api/tweets/:tweet_id', tweetContorller.getTweet) -router.get('/api/tweets', tweetContorller.getTweets) +router.get('/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetContorller.getTweet) +router.get('/api/tweets', authenticated, authenticatedUser, tweetContorller.getTweets) router.use('/', apiErrorHandler) From ea808235b908863a1da1f41b756fcd4d3622a61b Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 22:44:52 +0800 Subject: [PATCH 043/170] feat: add likeTweet --- controllers/apis/tweet-controller.js | 31 +++++++++++++++++++++++++++- routes/index.js | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 77d7f14735..f10a7417c3 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,4 +1,5 @@ -const { Tweet } = require('../../models') +const { Tweet, Like } = require('../../models') +const helpers = require('../../_helpers') const tweetContorller = { getTweets: async (req, res, next) => { @@ -20,6 +21,34 @@ const tweetContorller = { } catch (err) { next(err) } + }, + likeTweet: async (req, res, next) => { + try { + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id + const [tweet, like] = await Promise.all([ + Tweet.findByPk(tweetId), + Like.findOne({ + where: { + userId, + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (like) throw new Error('You have liked this tweet!') + const createdLike = await Like.create({ + userId, + tweetId + }) + res.json({ + status: 'success', + data: createdLike + }) + } catch (err) { + next(err) + } } } diff --git a/routes/index.js b/routes/index.js index 036ca1fe83..1ad0b3bfd4 100644 --- a/routes/index.js +++ b/routes/index.js @@ -21,6 +21,7 @@ router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, us router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) // api/tweets +router.post('/api/tweets/:tweet_id/like', authenticated, authenticatedUser, tweetContorller.likeTweet) router.get('/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetContorller.getTweet) router.get('/api/tweets', authenticated, authenticatedUser, tweetContorller.getTweets) From 4f50bf45cd17ad672c65764544cb51ff1cd6770b Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 23:09:01 +0800 Subject: [PATCH 044/170] feat: add like seeder --- seeders/20230821081029-replies-seed-file.js | 1 - seeders/20230824144658-likes-seed-file.js.js | 33 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 seeders/20230824144658-likes-seed-file.js.js diff --git a/seeders/20230821081029-replies-seed-file.js b/seeders/20230821081029-replies-seed-file.js index ff65ca0605..f72ce53031 100644 --- a/seeders/20230821081029-replies-seed-file.js +++ b/seeders/20230821081029-replies-seed-file.js @@ -8,7 +8,6 @@ module.exports = { const userData = await User.findAll({ raw: true, nest: true, - // where: { role: 'user' }, attributes: ['id'] }) const tweetData = await Tweet.findAll({ diff --git a/seeders/20230824144658-likes-seed-file.js.js b/seeders/20230824144658-likes-seed-file.js.js new file mode 100644 index 0000000000..232fe1d350 --- /dev/null +++ b/seeders/20230824144658-likes-seed-file.js.js @@ -0,0 +1,33 @@ +'use strict' + +module.exports = { + up: async (queryInterface, Sequelize) => { + const users = await queryInterface.sequelize.query( + 'SELECT id FROM Users WHERE role = "user";', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + + const tweets = await queryInterface.sequelize.query( + 'SELECT id FROM Tweets;', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + + const likes = [] + + tweets.forEach(tweet => { + likes.push( + ...Array.from({ length: 5 }, () => ({ + User_id: users[Math.floor(Math.random() * users.length)].id, + Tweet_id: tweet.id, + created_at: new Date(), + updated_at: new Date() + }) + )) + }) + await queryInterface.bulkInsert('Likes', likes) + }, + + down: async (queryInterface, Sequelize) => { + return queryInterface.bulkDelete('Likes', null, {}) + } +} From 3dd0b51febf08fb00ba2ecb00781830e1212d661 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 23:31:16 +0800 Subject: [PATCH 045/170] feat: add likeTweet --- controllers/apis/tweet-controller.js | 14 +++++++++++--- routes/index.js | 1 - 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index f10a7417c3..2525bd066e 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -7,7 +7,11 @@ const tweetContorller = { const tweets = await Tweet.findAll({ raw: true }) - res.json(tweets) + if (!tweets) throw new Error("Tweet didn't exist!") + res.json({ + status: 'success', + data: tweets + }) } catch (err) { next(err) } @@ -15,9 +19,13 @@ const tweetContorller = { getTweet: async (req, res, next) => { try { const tweetId = req.params.tweet_id - const tweet = await Tweet.findByPk(tweetId) - res.json(tweet) + + if (!tweet) throw new Error("Tweet didn't exist!") + res.json({ + status: 'success', + data: tweet + }) } catch (err) { next(err) } diff --git a/routes/index.js b/routes/index.js index 1ad0b3bfd4..cb8574a33b 100644 --- a/routes/index.js +++ b/routes/index.js @@ -11,7 +11,6 @@ const { authenticated, authenticatedAdmin, authenticatedUser } = require('../mid // api/admin router.use('/api/admin', authenticated, authenticatedAdmin, admin) -// router.use("/api/admin", admin); // api/users // router.get('/api/users', userController.getUsers) From d2b1095d9f2e5f01af282d61c7cb32d0aa838fe1 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 24 Aug 2023 23:44:19 +0800 Subject: [PATCH 046/170] feat: add unlike --- controllers/apis/tweet-controller.js | 34 +++++++++++++++++++++++++++- routes/index.js | 1 + 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 2525bd066e..b66b06e627 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -52,7 +52,39 @@ const tweetContorller = { }) res.json({ status: 'success', - data: createdLike + data: createdLike, + Boolean: true + }) + } catch (err) { + next(err) + } + }, + unlikeTweet: async (req, res, next) => { + try { + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id + const [tweet, like] = await Promise.all([ + Tweet.findByPk(tweetId), + Like.findOne({ + where: { + userId, + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (!like) throw new Error("You haven't liked this tweet!") + const unlike = await Like.destroy({ + where: { + userId, + tweetId + } + }) + res.json({ + status: 'success', + data: unlike, + Boolean: false }) } catch (err) { next(err) diff --git a/routes/index.js b/routes/index.js index cb8574a33b..86bf9eaea5 100644 --- a/routes/index.js +++ b/routes/index.js @@ -21,6 +21,7 @@ router.get('/api/users/:id', authenticated, authenticatedUser, userController.ge // api/tweets router.post('/api/tweets/:tweet_id/like', authenticated, authenticatedUser, tweetContorller.likeTweet) +router.post('/api/tweets/:tweet_id/unlike', authenticated, authenticatedUser, tweetContorller.unlikeTweet) router.get('/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetContorller.getTweet) router.get('/api/tweets', authenticated, authenticatedUser, tweetContorller.getTweets) From 95f8825da2a1e0a341b8965da090bcf086e02027 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Fri, 25 Aug 2023 00:02:58 +0800 Subject: [PATCH 047/170] fix: to pass test --- controllers/apis/tweet-controller.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index b66b06e627..3637442452 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -9,8 +9,7 @@ const tweetContorller = { }) if (!tweets) throw new Error("Tweet didn't exist!") res.json({ - status: 'success', - data: tweets + tweets }) } catch (err) { next(err) From 0746bde81afb00582a0d92d72b7b1f5b42d4fc39 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 25 Aug 2023 10:40:29 +0800 Subject: [PATCH 048/170] feat: add tweetcontroller --- config/passport.js | 1 - controllers/apis/tweet-controller.js | 24 +++++++++ routes/index.js | 75 +++++++++++++++++++++++++--- 3 files changed, 91 insertions(+), 9 deletions(-) diff --git a/config/passport.js b/config/passport.js index c6b67a4b85..9fe48b493e 100644 --- a/config/passport.js +++ b/config/passport.js @@ -5,7 +5,6 @@ const passportJWT = require('passport-jwt') const JWTStrategy = passportJWT.Strategy const ExtractJWT = passportJWT.ExtractJwt - const jwtOptions = { jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), secretOrKey: process.env.JWT_SECRET diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 3637442452..7b6b178de1 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -88,6 +88,30 @@ const tweetContorller = { } catch (err) { next(err) } + }, + createTweet: async (req, res, next) => { + try { + } catch (err) { + next(err) + } + }, + getReplies: async (req, res, next) => { + try { + } catch (err) { + next(err) + } + }, + createReply: async (req, res, next) => { + try { + } catch (err) { + next(err) + } + }, + getLikes: async (req, res, next) => { + try { + } catch (err) { + next(err) + } } } diff --git a/routes/index.js b/routes/index.js index 86bf9eaea5..f4e6e0c906 100644 --- a/routes/index.js +++ b/routes/index.js @@ -4,10 +4,14 @@ const router = express.Router() const admin = require('./modules/admin') const userController = require('../controllers/apis/user-controller') -const tweetContorller = require('../controllers/apis/tweet-controller') +const tweetController = require('../controllers/apis/tweet-controller') const { apiErrorHandler } = require('../middleware/error-handler') -const { authenticated, authenticatedAdmin, authenticatedUser } = require('../middleware/api-auth') +const { + authenticated, + authenticatedAdmin, + authenticatedUser +} = require('../middleware/api-auth') // api/admin router.use('/api/admin', authenticated, authenticatedAdmin, admin) @@ -16,14 +20,69 @@ router.use('/api/admin', authenticated, authenticatedAdmin, admin) // router.get('/api/users', userController.getUsers) router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) -router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) -router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) +router.get( + '/api/users/:id/replied_tweets', + authenticated, + authenticatedUser, + userController.getUserReplies +) +router.get( + '/api/users/:id', + authenticated, + authenticatedUser, + userController.getUser +) // api/tweets -router.post('/api/tweets/:tweet_id/like', authenticated, authenticatedUser, tweetContorller.likeTweet) -router.post('/api/tweets/:tweet_id/unlike', authenticated, authenticatedUser, tweetContorller.unlikeTweet) -router.get('/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetContorller.getTweet) -router.get('/api/tweets', authenticated, authenticatedUser, tweetContorller.getTweets) + +router.get( + '/api/tweets/:tweet_id/replies', + authenticated, + authenticatedUser, + tweetController.getReplies +) +router.post( + '/api/tweets/:tweet_id/replies', + authenticated, + authenticatedUser, + tweetController.createReply +) +router.get( + '/api/tweets/:tweet_id/likes', + authenticated, + authenticatedUser, + tweetController.getLikes +) +router.post( + '/api/tweets/:tweet_id/like', + authenticated, + authenticatedUser, + tweetController.likeTweet +) +router.post( + '/api/tweets/:tweet_id/unlike', + authenticated, + authenticatedUser, + tweetController.unlikeTweet +) +router.post( + '/api/tweets/:tweet_id', + authenticated, + authenticatedUser, + tweetController.createTweet +) +router.get( + '/api/tweets/:tweet_id', + authenticated, + authenticatedUser, + tweetController.getTweet +) +router.get( + '/api/tweets', + authenticated, + authenticatedUser, + tweetController.getTweets +) router.use('/', apiErrorHandler) From 8fcf6a57c6a8ddc4592a326bcc56a3a497fde96c Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 25 Aug 2023 15:11:49 +0800 Subject: [PATCH 049/170] =?UTF-8?q?feat:=20=E5=8F=96=E5=BE=97=E6=9F=90?= =?UTF-8?q?=E4=B8=80=E5=89=87=E8=B2=BC=E6=96=87=E6=89=80=E6=9C=89=E7=95=99?= =?UTF-8?q?=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/passport.js | 2 +- controllers/apis/tweet-controller.js | 60 ++++++++++++++++++++++- migrations/20190115071420-create-tweet.js | 9 ++++ models/reply.js | 5 +- routes/index.js | 11 +++-- 5 files changed, 79 insertions(+), 8 deletions(-) create mode 100644 migrations/20190115071420-create-tweet.js diff --git a/config/passport.js b/config/passport.js index 9fe48b493e..256593eb74 100644 --- a/config/passport.js +++ b/config/passport.js @@ -1,6 +1,6 @@ const passport = require('passport') const db = require('../models') -const { User, Tweet, Reply, Followship } = db +const { User } = db const passportJWT = require('passport-jwt') const JWTStrategy = passportJWT.Strategy const ExtractJWT = passportJWT.ExtractJwt diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 7b6b178de1..e938c6a770 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,4 +1,4 @@ -const { Tweet, Like } = require('../../models') +const { Tweet, Like, Reply, User } = require('../../models') const helpers = require('../../_helpers') const tweetContorller = { @@ -91,12 +91,70 @@ const tweetContorller = { }, createTweet: async (req, res, next) => { try { + const { description } = req.body + if (!description) throw new Error('文章內容不可為空白') + const createdTweet = await Tweet.create({ + description, + createdAt: new Date(), + updatedAt: new Date() + }) + res.status(200).json({ + status: 'success', + message: 'Successfully create tweet.', + data: createdTweet + }) } catch (err) { next(err) } }, getReplies: async (req, res, next) => { try { + const tweetId = req.params.tweet_id + const replies = await Reply.findAll({ + where: { tweetId }, + include: [ + { + model: User, + as: 'replier', + attributes: { exclude: ['password'] } + }, + { + model: Tweet, + as: 'tweetreply', + + include: [ + { + model: User, + as: 'author', + attributes: ['account', 'name', 'avatar'] + } + ] + } + ], + order: [['createdAt', 'DESC']], + nest: true + // raw: true // 為何設true就無法取資料? + }) + + if (!replies) throw new Error('This tweet has no replies') + // console.log(replies); + const repliesData = replies.map(reply => ({ + replyId: reply.id, + comment: reply.comment, + replierId: reply.replier.id, + replierName: reply.replier.name, + replierAvatar: reply.replier.avatar, + replierAccount: reply.replier.account, + createdAt: reply.createdAt, + tweetId: reply.TweetId, + tweetBelongerName: reply.tweetreply.author.name, + tweetBelongerAccount: reply.tweetreply.author.account + })) + console.log(repliesData) + res.json({ + status: 'success', + data: repliesData + }) } catch (err) { next(err) } diff --git a/migrations/20190115071420-create-tweet.js b/migrations/20190115071420-create-tweet.js new file mode 100644 index 0000000000..e436c71f81 --- /dev/null +++ b/migrations/20190115071420-create-tweet.js @@ -0,0 +1,9 @@ +module.exports = { + up: function (queryInterface, Sequelize) { + return Promise.resolve() + }, + + down: function (queryInterface) { + return Promise.resolve() + } +} diff --git a/models/reply.js b/models/reply.js index 1aa4851932..340a7ccf98 100644 --- a/models/reply.js +++ b/models/reply.js @@ -10,7 +10,10 @@ module.exports = (sequelize, DataTypes) => { static associate (models) { // define association here - Reply.belongsTo(models.Tweet, { foreignKey: 'tweetId', as: 'tweetreply' }) + Reply.belongsTo(models.Tweet, { + foreignKey: 'tweetId', + as: 'tweetreply' + }) Reply.belongsTo(models.User, { foreignKey: 'userId', as: 'replier' }) } } diff --git a/routes/index.js b/routes/index.js index f4e6e0c906..6d617007a3 100644 --- a/routes/index.js +++ b/routes/index.js @@ -65,17 +65,18 @@ router.post( authenticatedUser, tweetController.unlikeTweet ) -router.post( + +router.get( '/api/tweets/:tweet_id', authenticated, authenticatedUser, - tweetController.createTweet + tweetController.getTweet ) -router.get( - '/api/tweets/:tweet_id', +router.post( + '/api/tweets', authenticated, authenticatedUser, - tweetController.getTweet + tweetController.createTweet ) router.get( '/api/tweets', From 774e9ee769aed394d737e7647eeb3aee7ddd493b Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 25 Aug 2023 16:10:17 +0800 Subject: [PATCH 050/170] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=B8=80?= =?UTF-8?q?=E7=AD=86=E7=95=99=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/apis/tweet-controller.js | 184 +++++++++++++----------- controllers/apis/user-controller.js | 200 ++++++++++++++------------- 2 files changed, 209 insertions(+), 175 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index e938c6a770..4d6c5a79f5 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,144 +1,147 @@ -const { Tweet, Like, Reply, User } = require('../../models') -const helpers = require('../../_helpers') +const { Tweet, Like, Reply, User } = require("../../models"); +const helpers = require("../../_helpers"); const tweetContorller = { getTweets: async (req, res, next) => { try { const tweets = await Tweet.findAll({ - raw: true - }) - if (!tweets) throw new Error("Tweet didn't exist!") + raw: true, + }); + if (!tweets) throw new Error("Tweet didn't exist!"); res.json({ - tweets - }) + tweets, + }); } catch (err) { - next(err) + next(err); } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const tweet = await Tweet.findByPk(tweetId) + const tweetId = req.params.tweet_id; + const tweet = await Tweet.findByPk(tweetId); - if (!tweet) throw new Error("Tweet didn't exist!") + if (!tweet) throw new Error("Tweet didn't exist!"); res.json({ - status: 'success', - data: tweet - }) + status: "success", + data: tweet, + }); } catch (err) { - next(err) + next(err); } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (like) throw new Error('You have liked this tweet!') + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (like) throw new Error("You have liked this tweet!"); const createdLike = await Like.create({ userId, - tweetId - }) + tweetId, + }); res.json({ - status: 'success', + status: "success", data: createdLike, - Boolean: true - }) + Boolean: true, + }); } catch (err) { - next(err) + next(err); } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (!like) throw new Error("You haven't liked this tweet!") + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!like) throw new Error("You haven't liked this tweet!"); const unlike = await Like.destroy({ where: { userId, - tweetId - } - }) + tweetId, + }, + }); res.json({ - status: 'success', + status: "success", data: unlike, - Boolean: false - }) + Boolean: false, + }); } catch (err) { - next(err) + next(err); } }, createTweet: async (req, res, next) => { try { - const { description } = req.body - if (!description) throw new Error('文章內容不可為空白') + const { description } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; + if (!description) throw new Error("文章內容不可為空白"); const createdTweet = await Tweet.create({ + userId, description, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create tweet.', - data: createdTweet - }) + status: "success", + message: "Successfully create tweet.", + data: createdTweet, + }); } catch (err) { - next(err) + next(err); } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ { model: User, - as: 'author', - attributes: ['account', 'name', 'avatar'] - } - ] - } + as: "author", + attributes: ["account", "name", "avatar"], + }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true + order: [["createdAt", "DESC"]], + nest: true, // raw: true // 為何設true就無法取資料? - }) + }); - if (!replies) throw new Error('This tweet has no replies') + if (!replies) throw new Error("This tweet has no replies"); // console.log(replies); - const repliesData = replies.map(reply => ({ + const repliesData = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -148,29 +151,48 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) - console.log(repliesData) + tweetBelongerAccount: reply.tweetreply.author.account, + })); + console.log(repliesData); res.json({ - status: 'success', - data: repliesData - }) + status: "success", + data: repliesData, + }); } catch (err) { - next(err) + next(err); } }, createReply: async (req, res, next) => { try { + const tweetId = req.params.tweet_id; + const { comment } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; + + if (!comment) throw new Error("回覆內容不可為空白"); + const replyData = await Reply.create({ + tweetId, + userId, + comment, + createdAt: new Date(), + updatedAt: new Date(), + }); + + res.json({ + status: "success", + message: "successfully created reply", + replyData, + }); } catch (err) { - next(err) + next(err); } }, getLikes: async (req, res, next) => { try { } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = tweetContorller +module.exports = tweetContorller; diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index cb8aa62f73..77046bd9e6 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,33 +1,29 @@ -const bcrypt = require('bcryptjs') -const jwt = require('jsonwebtoken') -const db = require('../../models') -const { getUser } = require('../../_helpers') +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken"); +const db = require("../../models"); +const { getUser } = require("../../_helpers"); -const { User, Tweet, Reply, Followship } = db -const { Op } = require('sequelize') +const { User, Tweet, Reply, Followship } = db; +const { Op } = require("sequelize"); const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body + const { account, name, email, password, checkPassword } = req.body; - if (!account || !name || !email || !password || !checkPassword) throw new Error('all the blanks are required') + if (!account || !name || !email || !password || !checkPassword) + throw new Error("all the blanks are required"); // 檢查帳號是否重複 - const user = await User.findOne( - { - where: { - [Op.or]: [ - { email }, - { account } - ] - } - } - ) + const user = await User.findOne({ + where: { + [Op.or]: [{ email }, { account }], + }, + }); if (user) { - if (user.account === account) throw new Error('account 已重複註冊!') - if (user.email === email) throw new Error('email 已重複註冊!') + if (user.account === account) throw new Error("account 已重複註冊!"); + if (user.email === email) throw new Error("email 已重複註冊!"); } const createdUser = await User.create({ @@ -35,112 +31,128 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: 'https://picsum.photos/100/100', - cover: 'https://picsum.photos/id/237/700/400', - role: 'user', + avatar: "https://picsum.photos/100/100", + cover: "https://picsum.photos/id/237/700/400", + role: "user", createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create user.', - data: createdUser - }) + status: "success", + message: "Successfully create user.", + data: createdUser, + }); } catch (err) { - next(err) + next(err); } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body - if (!account || !password) throw new Error('Please enter account and password') - - const user = await User.findOne({ where: { account } }) - if (!user) throw new Error('User does not exist') - if (user.role === 'admin') throw new Error('admin permission denied') - if (!bcrypt.compareSync(password, user.password)) throw new Error('Incorrect password') + const { account, password } = req.body; + if (!account || !password) + throw new Error("Please enter account and password"); + + const user = await User.findOne({ where: { account } }); + if (!user) throw new Error("User does not exist"); + if (user.role === "admin") throw new Error("admin permission denied"); + if (!bcrypt.compareSync(password, user.password)) + throw new Error("Incorrect password"); const payload = { id: user.id, account: user.account, - role: user.role - } - const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' }) - const userData = user.toJSON() + role: user.role, + }; + const token = jwt.sign(payload, process.env.JWT_SECRET, { + expiresIn: "30d", + }); + const userData = user.toJSON(); res.json({ - status: 'success', + status: "success", data: { token, - user: userData - } - }) + user: userData, + }, + }); } catch (err) { - next(err) + next(err); } }, getUser: async (req, res, next) => { try { - const { id } = req.params - const currentUserId = getUser(req).dataValues.id - console.log(currentUserId) - - const [user, tweetCount, followerCount, followingCount] = await Promise.all([ - User.findByPk(id, { raw: true, nest: true }), - Tweet.count({ - where: { UserId: id } - }), - Followship.count({ - where: { followerId: id } - }), - Followship.count({ - where: { followingId: id } - }) - ]) - - if (!user) return res.status(401).json({ status: 'error', message: 'This user does not exist' }) - - delete user.password - user.tweetCount = tweetCount - user.followerCount = followerCount - user.followingCount = followingCount + const { id } = req.params; + const currentUserId = getUser(req).dataValues.id; + console.log(currentUserId); + + const [user, tweetCount, followerCount, followingCount] = + await Promise.all([ + User.findByPk(id, { raw: true, nest: true }), + Tweet.count({ + where: { UserId: id }, + }), + Followship.count({ + where: { followerId: id }, + }), + Followship.count({ + where: { followingId: id }, + }), + ]); + + if (!user) + return res + .status(401) + .json({ status: "error", message: "This user does not exist" }); + + delete user.password; + user.tweetCount = tweetCount; + user.followerCount = followerCount; + user.followingCount = followingCount; if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) - user.isFollowed = checkUserFollowing.some(follow => follow.followingId === Number(id)) + raw: true, + }); + user.isFollowed = checkUserFollowing.some( + (follow) => follow.followingId === Number(id) + ); } - res.status(200).json(user) + res.status(200).json(user); } catch (err) { - next(err) + next(err); } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id + const userId = req.params.id; const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), Reply.findAll({ where: { UserId: userId }, include: [ - { model: User, as: 'replier', attributes: { exclude: ['password'] } }, + { + model: User, + as: "replier", + attributes: { exclude: ["password"] }, + }, { model: Tweet, - as: 'tweetreply', - include: [{ model: User, as: 'author', attributes: ['account', 'name'] }] - } + as: "tweetreply", + include: [ + { model: User, as: "author", attributes: ["account", "name"] }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true - } - )]) + order: [["createdAt", "DESC"]], + nest: true, + }), + ]); - console.log(user, replies) - const userRepliesResult = replies.map(reply => ({ + console.log(user, replies); + const userRepliesResult = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -150,17 +162,17 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - console.log(userRepliesResult) + console.log(userRepliesResult); - res.status(200).json(userRepliesResult) + res.status(200).json(userRepliesResult); } catch (err) { - console.error(err) - next(err) + console.error(err); + next(err); } - } -} + }, +}; -module.exports = userController +module.exports = userController; From 8e86f35877d432a9b7e4455e1506ee24ec2a9ef6 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 25 Aug 2023 17:15:10 +0800 Subject: [PATCH 051/170] =?UTF-8?q?feat:=20=E6=9F=A5=E7=9C=8B=E4=B8=80?= =?UTF-8?q?=E5=89=87=E8=B2=BC=E6=96=87=E6=89=80=E6=9C=89=E6=8C=89=E8=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/apis/tweet-controller.js | 224 +++++++++++++++------------ controllers/apis/user-controller.js | 168 ++++++++++---------- 2 files changed, 212 insertions(+), 180 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 4d6c5a79f5..c62f3532f2 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,147 +1,147 @@ -const { Tweet, Like, Reply, User } = require("../../models"); -const helpers = require("../../_helpers"); +const { Tweet, Like, Reply, User } = require('../../models') +const helpers = require('../../_helpers') const tweetContorller = { getTweets: async (req, res, next) => { try { const tweets = await Tweet.findAll({ - raw: true, - }); - if (!tweets) throw new Error("Tweet didn't exist!"); + raw: true + }) + if (!tweets) throw new Error("Tweet didn't exist!") res.json({ - tweets, - }); + tweets + }) } catch (err) { - next(err); + next(err) } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const tweet = await Tweet.findByPk(tweetId); + const tweetId = req.params.tweet_id + const tweet = await Tweet.findByPk(tweetId) - if (!tweet) throw new Error("Tweet didn't exist!"); + if (!tweet) throw new Error("Tweet didn't exist!") res.json({ - status: "success", - data: tweet, - }); + status: 'success', + data: tweet + }) } catch (err) { - next(err); + next(err) } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (like) throw new Error("You have liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (like) throw new Error('You have liked this tweet!') const createdLike = await Like.create({ userId, - tweetId, - }); + tweetId + }) res.json({ - status: "success", + status: 'success', data: createdLike, - Boolean: true, - }); + Boolean: true + }) } catch (err) { - next(err); + next(err) } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!like) throw new Error("You haven't liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (!like) throw new Error("You haven't liked this tweet!") const unlike = await Like.destroy({ where: { userId, - tweetId, - }, - }); + tweetId + } + }) res.json({ - status: "success", + status: 'success', data: unlike, - Boolean: false, - }); + Boolean: false + }) } catch (err) { - next(err); + next(err) } }, createTweet: async (req, res, next) => { try { - const { description } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; - if (!description) throw new Error("文章內容不可為空白"); + const { description } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id + if (!description) throw new Error('文章內容不可為空白') const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create tweet.", - data: createdTweet, - }); + status: 'success', + message: 'Successfully create tweet.', + data: createdTweet + }) } catch (err) { - next(err); + next(err) } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ { model: User, - as: "author", - attributes: ["account", "name", "avatar"], - }, - ], - }, + as: 'author', + attributes: ['account', 'name', 'avatar'] + } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, + order: [['createdAt', 'DESC']], + nest: true // raw: true // 為何設true就無法取資料? - }); + }) - if (!replies) throw new Error("This tweet has no replies"); - // console.log(replies); - const repliesData = replies.map((reply) => ({ + if (!replies) throw new Error('This tweet has no replies') + console.log(replies) + const repliesData = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -151,48 +151,82 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); - console.log(repliesData); + tweetBelongerAccount: reply.tweetreply.author.account + })) + // console.log(repliesData); res.json({ - status: "success", - data: repliesData, - }); + status: 'success', + data: repliesData + }) } catch (err) { - next(err); + next(err) } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const { comment } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const { comment } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id - if (!comment) throw new Error("回覆內容不可為空白"); + if (!comment) throw new Error('回覆內容不可為空白') const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.json({ - status: "success", - message: "successfully created reply", - replyData, - }); + status: 'success', + message: 'successfully created reply', + replyData + }) } catch (err) { - next(err); + next(err) } }, getLikes: async (req, res, next) => { try { + // const getUser = helpers.getUser(req); + const tweetId = req.params.tweet_id + const [tweet, likes] = await Promise.all([ + Tweet.findByPk(tweetId), + Like.findAll({ + where: { + tweetId + }, + nest: true, + raw: true, + include: [ + { + model: User, + attributes: { exclude: ['password', 'introduction', 'cover'] } + } + ] + }) + ]) + console.log(likes) + if (!tweet) throw new Error("Tweet didn't exist!") + if (!likes) throw new Error('NO ONE liked this tweet!') + const dataLike = likes.map(like => ({ + likedId: like.id, + likedTweetId: like.tweetId, + likedUserId: like.User.id, + likedUserName: like.User.name, + likedUserAccount: like.User.account, + likedUserAvatar: like.User.avatar + })) + res.json({ + status: 'success', + message: 'successfully get all the liked users', + dataLike + }) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = tweetContorller; +module.exports = tweetContorller diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 77046bd9e6..d9f82ade05 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,29 +1,28 @@ -const bcrypt = require("bcryptjs"); -const jwt = require("jsonwebtoken"); -const db = require("../../models"); -const { getUser } = require("../../_helpers"); +const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') +const db = require('../../models') +const { getUser } = require('../../_helpers') -const { User, Tweet, Reply, Followship } = db; -const { Op } = require("sequelize"); +const { User, Tweet, Reply, Followship } = db +const { Op } = require('sequelize') const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body; + const { account, name, email, password, checkPassword } = req.body - if (!account || !name || !email || !password || !checkPassword) - throw new Error("all the blanks are required"); + if (!account || !name || !email || !password || !checkPassword) { throw new Error('all the blanks are required') } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }], - }, - }); + [Op.or]: [{ email }, { account }] + } + }) if (user) { - if (user.account === account) throw new Error("account 已重複註冊!"); - if (user.email === email) throw new Error("email 已重複註冊!"); + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') } const createdUser = await User.create({ @@ -31,102 +30,101 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: "https://picsum.photos/100/100", - cover: "https://picsum.photos/id/237/700/400", - role: "user", + avatar: 'https://picsum.photos/100/100', + cover: 'https://picsum.photos/id/237/700/400', + role: 'user', createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create user.", - data: createdUser, - }); + status: 'success', + message: 'Successfully create user.', + data: createdUser + }) } catch (err) { - next(err); + next(err) } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body; - if (!account || !password) - throw new Error("Please enter account and password"); - - const user = await User.findOne({ where: { account } }); - if (!user) throw new Error("User does not exist"); - if (user.role === "admin") throw new Error("admin permission denied"); - if (!bcrypt.compareSync(password, user.password)) - throw new Error("Incorrect password"); + const { account, password } = req.body + if (!account || !password) { throw new Error('Please enter account and password') } + + const user = await User.findOne({ where: { account } }) + if (!user) throw new Error('User does not exist') + if (user.role === 'admin') throw new Error('admin permission denied') + if (!bcrypt.compareSync(password, user.password)) { throw new Error('Incorrect password') } const payload = { id: user.id, account: user.account, - role: user.role, - }; + role: user.role + } const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "30d", - }); - const userData = user.toJSON(); + expiresIn: '30d' + }) + const userData = user.toJSON() res.json({ - status: "success", + status: 'success', data: { token, - user: userData, - }, - }); + user: userData + } + }) } catch (err) { - next(err); + next(err) } }, getUser: async (req, res, next) => { try { - const { id } = req.params; - const currentUserId = getUser(req).dataValues.id; - console.log(currentUserId); + const { id } = req.params + const currentUserId = getUser(req).dataValues.id + console.log(currentUserId) const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id }, + where: { UserId: id } }), Followship.count({ - where: { followerId: id }, + where: { followerId: id } }), Followship.count({ - where: { followingId: id }, - }), - ]); + where: { followingId: id } + }) + ]) - if (!user) + if (!user) { return res .status(401) - .json({ status: "error", message: "This user does not exist" }); + .json({ status: 'error', message: 'This user does not exist' }) + } - delete user.password; - user.tweetCount = tweetCount; - user.followerCount = followerCount; - user.followingCount = followingCount; + delete user.password + user.tweetCount = tweetCount + user.followerCount = followerCount + user.followingCount = followingCount if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) user.isFollowed = checkUserFollowing.some( - (follow) => follow.followingId === Number(id) - ); + follow => follow.followingId === Number(id) + ) } - res.status(200).json(user); + res.status(200).json(user) } catch (err) { - next(err); + next(err) } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id; + const userId = req.params.id const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -135,24 +133,24 @@ const userController = { include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ - { model: User, as: "author", attributes: ["account", "name"] }, - ], - }, + { model: User, as: 'author', attributes: ['account', 'name'] } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, - }), - ]); + order: [['createdAt', 'DESC']], + nest: true + }) + ]) - console.log(user, replies); - const userRepliesResult = replies.map((reply) => ({ + console.log(user, replies) + const userRepliesResult = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -162,17 +160,17 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - console.log(userRepliesResult); + console.log(userRepliesResult) - res.status(200).json(userRepliesResult); + res.status(200).json(userRepliesResult) } catch (err) { - console.error(err); - next(err); + console.error(err) + next(err) } - }, -}; + } +} -module.exports = userController; +module.exports = userController From 26c83923afeba725deb4379bf6a09a42b169bd45 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 25 Aug 2023 17:38:26 +0800 Subject: [PATCH 052/170] fix: pass test --- controllers/apis/tweet-controller.js | 224 +++++++++++++-------------- 1 file changed, 110 insertions(+), 114 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index c62f3532f2..bfaa25fdf0 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,147 +1,142 @@ -const { Tweet, Like, Reply, User } = require('../../models') -const helpers = require('../../_helpers') +const { Tweet, Like, Reply, User } = require("../../models"); +const helpers = require("../../_helpers"); const tweetContorller = { getTweets: async (req, res, next) => { try { const tweets = await Tweet.findAll({ - raw: true - }) - if (!tweets) throw new Error("Tweet didn't exist!") - res.json({ - tweets - }) + raw: true, + }); + if (!tweets) throw new Error("Tweet didn't exist!"); + res.json(tweets); } catch (err) { - next(err) + next(err); } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const tweet = await Tweet.findByPk(tweetId) + const tweetId = req.params.tweet_id; + const tweet = await Tweet.findByPk(tweetId); - if (!tweet) throw new Error("Tweet didn't exist!") - res.json({ - status: 'success', - data: tweet - }) + if (!tweet) throw new Error("Tweet didn't exist!"); + res.json(tweet); } catch (err) { - next(err) + next(err); } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (like) throw new Error('You have liked this tweet!') + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (like) throw new Error("You have liked this tweet!"); const createdLike = await Like.create({ userId, - tweetId - }) + tweetId, + }); res.json({ - status: 'success', + status: "success", data: createdLike, - Boolean: true - }) + Boolean: true, + }); } catch (err) { - next(err) + next(err); } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (!like) throw new Error("You haven't liked this tweet!") + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!like) throw new Error("You haven't liked this tweet!"); const unlike = await Like.destroy({ where: { userId, - tweetId - } - }) + tweetId, + }, + }); res.json({ - status: 'success', + status: "success", data: unlike, - Boolean: false - }) + Boolean: false, + }); } catch (err) { - next(err) + next(err); } }, createTweet: async (req, res, next) => { try { - const { description } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id - if (!description) throw new Error('文章內容不可為空白') + const { description } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; + if (!description) throw new Error("文章內容不可為空白"); const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create tweet.', - data: createdTweet - }) + status: "success", + message: "Successfully create tweet.", + data: createdTweet, + }); } catch (err) { - next(err) + next(err); } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ { model: User, - as: 'author', - attributes: ['account', 'name', 'avatar'] - } - ] - } + as: "author", + attributes: ["account", "name", "avatar"], + }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true + order: [["createdAt", "DESC"]], + nest: true, // raw: true // 為何設true就無法取資料? - }) + }); - if (!replies) throw new Error('This tweet has no replies') - console.log(replies) - const repliesData = replies.map(reply => ({ + if (!replies) throw new Error("This tweet has no replies"); + console.log(replies); + const repliesData = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -151,82 +146,83 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); // console.log(repliesData); - res.json({ - status: 'success', - data: repliesData - }) + // res.json({ + // status: "success", + // data: repliesData, + // }); + res.status(200).json(repliesData); } catch (err) { - next(err) + next(err); } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const { comment } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const { comment } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; - if (!comment) throw new Error('回覆內容不可為空白') + if (!comment) throw new Error("回覆內容不可為空白"); const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.json({ - status: 'success', - message: 'successfully created reply', - replyData - }) + status: "success", + message: "successfully created reply", + replyData, + }); } catch (err) { - next(err) + next(err); } }, getLikes: async (req, res, next) => { try { // const getUser = helpers.getUser(req); - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId + tweetId, }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ['password', 'introduction', 'cover'] } - } - ] - }) - ]) - console.log(likes) - if (!tweet) throw new Error("Tweet didn't exist!") - if (!likes) throw new Error('NO ONE liked this tweet!') - const dataLike = likes.map(like => ({ + attributes: { exclude: ["password", "introduction", "cover"] }, + }, + ], + }), + ]); + console.log(likes); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!likes) throw new Error("NO ONE liked this tweet!"); + const dataLike = likes.map((like) => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar - })) + likedUserAvatar: like.User.avatar, + })); res.json({ - status: 'success', - message: 'successfully get all the liked users', - dataLike - }) + status: "success", + message: "successfully get all the liked users", + dataLike, + }); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = tweetContorller +module.exports = tweetContorller; From d717e286d75996dcf83dc32f04b6fce99363ea60 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 25 Aug 2023 18:28:03 +0800 Subject: [PATCH 053/170] fix: bugs --- app.js | 2 - controllers/apis/tweet-controller.js | 16 +-- controllers/apis/user-controller.js | 167 ++++++++++++++------------- routes/index.js | 66 +++++------ 4 files changed, 124 insertions(+), 127 deletions(-) diff --git a/app.js b/app.js index 44ddb481de..b9f893c948 100644 --- a/app.js +++ b/app.js @@ -3,9 +3,7 @@ if (process.NODE_ENV !== 'production') { } // require('dotenv').config() const express = require('express') -const helpers = require('./_helpers') const bodyParser = require('body-parser') -const session = require('express-session') const routes = require('./routes') const passport = require('./config/passport') diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index bfaa25fdf0..cc6b862d0b 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -47,7 +47,7 @@ const tweetContorller = { res.json({ status: "success", data: createdLike, - Boolean: true, + isLiked: true, }); } catch (err) { next(err); @@ -77,8 +77,7 @@ const tweetContorller = { }); res.json({ status: "success", - data: unlike, - Boolean: false, + isLiked: false, }); } catch (err) { next(err); @@ -148,11 +147,7 @@ const tweetContorller = { tweetBelongerName: reply.tweetreply.author.name, tweetBelongerAccount: reply.tweetreply.author.account, })); - // console.log(repliesData); - // res.json({ - // status: "success", - // data: repliesData, - // }); + res.status(200).json(repliesData); } catch (err) { next(err); @@ -185,7 +180,6 @@ const tweetContorller = { }, getLikes: async (req, res, next) => { try { - // const getUser = helpers.getUser(req); const tweetId = req.params.tweet_id; const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), @@ -206,7 +200,7 @@ const tweetContorller = { console.log(likes); if (!tweet) throw new Error("Tweet didn't exist!"); if (!likes) throw new Error("NO ONE liked this tweet!"); - const dataLike = likes.map((like) => ({ + const likedData = likes.map((like) => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, @@ -217,7 +211,7 @@ const tweetContorller = { res.json({ status: "success", message: "successfully get all the liked users", - dataLike, + likedData, }); } catch (err) { next(err); diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index d9f82ade05..a9ff3ceba1 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,28 +1,30 @@ -const bcrypt = require('bcryptjs') -const jwt = require('jsonwebtoken') -const db = require('../../models') -const { getUser } = require('../../_helpers') +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken"); +const db = require("../../models"); +const { getUser } = require("../../_helpers"); -const { User, Tweet, Reply, Followship } = db -const { Op } = require('sequelize') +const { User, Tweet, Reply, Followship } = db; +const { Op } = require("sequelize"); const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body + const { account, name, email, password, checkPassword } = req.body; - if (!account || !name || !email || !password || !checkPassword) { throw new Error('all the blanks are required') } + if (!account || !name || !email || !password || !checkPassword) { + throw new Error("all the blanks are required"); + } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }] - } - }) + [Op.or]: [{ email }, { account }], + }, + }); if (user) { - if (user.account === account) throw new Error('account 已重複註冊!') - if (user.email === email) throw new Error('email 已重複註冊!') + if (user.account === account) throw new Error("account 已重複註冊!"); + if (user.email === email) throw new Error("email 已重複註冊!"); } const createdUser = await User.create({ @@ -30,101 +32,104 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: 'https://picsum.photos/100/100', - cover: 'https://picsum.photos/id/237/700/400', - role: 'user', + avatar: "https://picsum.photos/100/100", + cover: "https://picsum.photos/id/237/700/400", + role: "user", createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create user.', - data: createdUser - }) + status: "success", + message: "Successfully create user.", + data: createdUser, + }); } catch (err) { - next(err) + next(err); } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body - if (!account || !password) { throw new Error('Please enter account and password') } + const { account, password } = req.body; + if (!account || !password) { + throw new Error("Please enter account and password"); + } - const user = await User.findOne({ where: { account } }) - if (!user) throw new Error('User does not exist') - if (user.role === 'admin') throw new Error('admin permission denied') - if (!bcrypt.compareSync(password, user.password)) { throw new Error('Incorrect password') } + const user = await User.findOne({ where: { account } }); + if (!user) throw new Error("User does not exist"); + if (user.role === "admin") throw new Error("admin permission denied"); + if (!bcrypt.compareSync(password, user.password)) { + throw new Error("Incorrect password"); + } const payload = { id: user.id, account: user.account, - role: user.role - } + role: user.role, + }; const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: '30d' - }) - const userData = user.toJSON() + expiresIn: "30d", + }); + const userData = user.toJSON(); res.json({ - status: 'success', + status: "success", data: { token, - user: userData - } - }) + user: userData, + }, + }); } catch (err) { - next(err) + next(err); } }, getUser: async (req, res, next) => { try { - const { id } = req.params - const currentUserId = getUser(req).dataValues.id - console.log(currentUserId) + const { id } = req.params; + const currentUserId = getUser(req).dataValues.id; + console.log(currentUserId); const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id } + where: { UserId: id }, }), Followship.count({ - where: { followerId: id } + where: { followerId: id }, }), Followship.count({ - where: { followingId: id } - }) - ]) + where: { followingId: id }, + }), + ]); if (!user) { return res .status(401) - .json({ status: 'error', message: 'This user does not exist' }) + .json({ status: "error", message: "This user does not exist" }); } - delete user.password - user.tweetCount = tweetCount - user.followerCount = followerCount - user.followingCount = followingCount + delete user.password; + user.tweetCount = tweetCount; + user.followerCount = followerCount; + user.followingCount = followingCount; if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); user.isFollowed = checkUserFollowing.some( - follow => follow.followingId === Number(id) - ) + (follow) => follow.followingId === Number(id) + ); } - - res.status(200).json(user) + res.status(200).json(user); } catch (err) { - next(err) + next(err); } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id + const userId = req.params.id; const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -133,24 +138,24 @@ const userController = { include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ - { model: User, as: 'author', attributes: ['account', 'name'] } - ] - } + { model: User, as: "author", attributes: ["account", "name"] }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true - }) - ]) + order: [["createdAt", "DESC"]], + nest: true, + }), + ]); - console.log(user, replies) - const userRepliesResult = replies.map(reply => ({ + console.log(user, replies); + const userRepliesResult = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -160,17 +165,17 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - console.log(userRepliesResult) + console.log(userRepliesResult); - res.status(200).json(userRepliesResult) + res.status(200).json(userRepliesResult); } catch (err) { - console.error(err) - next(err) + console.error(err); + next(err); } - } -} + }, +}; -module.exports = userController +module.exports = userController; diff --git a/routes/index.js b/routes/index.js index 6d617007a3..d3ec157d5d 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,90 +1,90 @@ -const express = require('express') -const router = express.Router() +const express = require("express"); +const router = express.Router(); -const admin = require('./modules/admin') +const admin = require("./modules/admin"); -const userController = require('../controllers/apis/user-controller') -const tweetController = require('../controllers/apis/tweet-controller') +const userController = require("../controllers/apis/user-controller"); +const tweetController = require("../controllers/apis/tweet-controller"); -const { apiErrorHandler } = require('../middleware/error-handler') +const { apiErrorHandler } = require("../middleware/error-handler"); const { authenticated, authenticatedAdmin, - authenticatedUser -} = require('../middleware/api-auth') + authenticatedUser, +} = require("../middleware/api-auth"); // api/admin -router.use('/api/admin', authenticated, authenticatedAdmin, admin) +router.use("/api/admin", authenticated, authenticatedAdmin, admin); // api/users // router.get('/api/users', userController.getUsers) -router.post('/api/users', userController.signUp) -router.post('/api/users/signin', userController.signIn) +router.post("/api/users", userController.signUp); +router.post("/api/users/signin", userController.signIn); router.get( - '/api/users/:id/replied_tweets', + "/api/users/:id/replied_tweets", authenticated, authenticatedUser, userController.getUserReplies -) +); router.get( - '/api/users/:id', + "/api/users/:id", authenticated, authenticatedUser, userController.getUser -) +); // api/tweets router.get( - '/api/tweets/:tweet_id/replies', + "/api/tweets/:tweet_id/replies", authenticated, authenticatedUser, tweetController.getReplies -) +); router.post( - '/api/tweets/:tweet_id/replies', + "/api/tweets/:tweet_id/replies", authenticated, authenticatedUser, tweetController.createReply -) +); router.get( - '/api/tweets/:tweet_id/likes', + "/api/tweets/:tweet_id/likes", authenticated, authenticatedUser, tweetController.getLikes -) +); router.post( - '/api/tweets/:tweet_id/like', + "/api/tweets/:tweet_id/like", authenticated, authenticatedUser, tweetController.likeTweet -) +); router.post( - '/api/tweets/:tweet_id/unlike', + "/api/tweets/:tweet_id/unlike", authenticated, authenticatedUser, tweetController.unlikeTweet -) +); router.get( - '/api/tweets/:tweet_id', + "/api/tweets/:tweet_id", authenticated, authenticatedUser, tweetController.getTweet -) +); router.post( - '/api/tweets', + "/api/tweets", authenticated, authenticatedUser, tweetController.createTweet -) +); router.get( - '/api/tweets', + "/api/tweets", authenticated, authenticatedUser, tweetController.getTweets -) +); -router.use('/', apiErrorHandler) +router.use("/", apiErrorHandler); -module.exports = router +module.exports = router; From 1eb267c0eb82ea35cd502a50d93e4a3ea5acbe9e Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 25 Aug 2023 18:28:38 +0800 Subject: [PATCH 054/170] fix: es lint --- controllers/apis/tweet-controller.js | 212 +++++++++++++-------------- controllers/apis/user-controller.js | 160 ++++++++++---------- routes/index.js | 66 ++++----- 3 files changed, 219 insertions(+), 219 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index cc6b862d0b..7b683dd248 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,141 +1,141 @@ -const { Tweet, Like, Reply, User } = require("../../models"); -const helpers = require("../../_helpers"); +const { Tweet, Like, Reply, User } = require('../../models') +const helpers = require('../../_helpers') const tweetContorller = { getTweets: async (req, res, next) => { try { const tweets = await Tweet.findAll({ - raw: true, - }); - if (!tweets) throw new Error("Tweet didn't exist!"); - res.json(tweets); + raw: true + }) + if (!tweets) throw new Error("Tweet didn't exist!") + res.json(tweets) } catch (err) { - next(err); + next(err) } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const tweet = await Tweet.findByPk(tweetId); + const tweetId = req.params.tweet_id + const tweet = await Tweet.findByPk(tweetId) - if (!tweet) throw new Error("Tweet didn't exist!"); - res.json(tweet); + if (!tweet) throw new Error("Tweet didn't exist!") + res.json(tweet) } catch (err) { - next(err); + next(err) } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (like) throw new Error("You have liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (like) throw new Error('You have liked this tweet!') const createdLike = await Like.create({ userId, - tweetId, - }); + tweetId + }) res.json({ - status: "success", + status: 'success', data: createdLike, - isLiked: true, - }); + isLiked: true + }) } catch (err) { - next(err); + next(err) } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!like) throw new Error("You haven't liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (!like) throw new Error("You haven't liked this tweet!") const unlike = await Like.destroy({ where: { userId, - tweetId, - }, - }); + tweetId + } + }) res.json({ - status: "success", - isLiked: false, - }); + status: 'success', + isLiked: false + }) } catch (err) { - next(err); + next(err) } }, createTweet: async (req, res, next) => { try { - const { description } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; - if (!description) throw new Error("文章內容不可為空白"); + const { description } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id + if (!description) throw new Error('文章內容不可為空白') const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create tweet.", - data: createdTweet, - }); + status: 'success', + message: 'Successfully create tweet.', + data: createdTweet + }) } catch (err) { - next(err); + next(err) } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ { model: User, - as: "author", - attributes: ["account", "name", "avatar"], - }, - ], - }, + as: 'author', + attributes: ['account', 'name', 'avatar'] + } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, + order: [['createdAt', 'DESC']], + nest: true // raw: true // 為何設true就無法取資料? - }); + }) - if (!replies) throw new Error("This tweet has no replies"); - console.log(replies); - const repliesData = replies.map((reply) => ({ + if (!replies) throw new Error('This tweet has no replies') + console.log(replies) + const repliesData = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -145,78 +145,78 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(repliesData); + res.status(200).json(repliesData) } catch (err) { - next(err); + next(err) } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const { comment } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const { comment } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id - if (!comment) throw new Error("回覆內容不可為空白"); + if (!comment) throw new Error('回覆內容不可為空白') const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.json({ - status: "success", - message: "successfully created reply", - replyData, - }); + status: 'success', + message: 'successfully created reply', + replyData + }) } catch (err) { - next(err); + next(err) } }, getLikes: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId, + tweetId }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ["password", "introduction", "cover"] }, - }, - ], - }), - ]); - console.log(likes); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!likes) throw new Error("NO ONE liked this tweet!"); - const likedData = likes.map((like) => ({ + attributes: { exclude: ['password', 'introduction', 'cover'] } + } + ] + }) + ]) + console.log(likes) + if (!tweet) throw new Error("Tweet didn't exist!") + if (!likes) throw new Error('NO ONE liked this tweet!') + const likedData = likes.map(like => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar, - })); + likedUserAvatar: like.User.avatar + })) res.json({ - status: "success", - message: "successfully get all the liked users", - likedData, - }); + status: 'success', + message: 'successfully get all the liked users', + likedData + }) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = tweetContorller; +module.exports = tweetContorller diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index a9ff3ceba1..1afa7fbfa7 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,30 +1,30 @@ -const bcrypt = require("bcryptjs"); -const jwt = require("jsonwebtoken"); -const db = require("../../models"); -const { getUser } = require("../../_helpers"); +const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') +const db = require('../../models') +const { getUser } = require('../../_helpers') -const { User, Tweet, Reply, Followship } = db; -const { Op } = require("sequelize"); +const { User, Tweet, Reply, Followship } = db +const { Op } = require('sequelize') const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body; + const { account, name, email, password, checkPassword } = req.body if (!account || !name || !email || !password || !checkPassword) { - throw new Error("all the blanks are required"); + throw new Error('all the blanks are required') } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }], - }, - }); + [Op.or]: [{ email }, { account }] + } + }) if (user) { - if (user.account === account) throw new Error("account 已重複註冊!"); - if (user.email === email) throw new Error("email 已重複註冊!"); + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') } const createdUser = await User.create({ @@ -32,104 +32,104 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: "https://picsum.photos/100/100", - cover: "https://picsum.photos/id/237/700/400", - role: "user", + avatar: 'https://picsum.photos/100/100', + cover: 'https://picsum.photos/id/237/700/400', + role: 'user', createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create user.", - data: createdUser, - }); + status: 'success', + message: 'Successfully create user.', + data: createdUser + }) } catch (err) { - next(err); + next(err) } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body; + const { account, password } = req.body if (!account || !password) { - throw new Error("Please enter account and password"); + throw new Error('Please enter account and password') } - const user = await User.findOne({ where: { account } }); - if (!user) throw new Error("User does not exist"); - if (user.role === "admin") throw new Error("admin permission denied"); + const user = await User.findOne({ where: { account } }) + if (!user) throw new Error('User does not exist') + if (user.role === 'admin') throw new Error('admin permission denied') if (!bcrypt.compareSync(password, user.password)) { - throw new Error("Incorrect password"); + throw new Error('Incorrect password') } const payload = { id: user.id, account: user.account, - role: user.role, - }; + role: user.role + } const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "30d", - }); - const userData = user.toJSON(); + expiresIn: '30d' + }) + const userData = user.toJSON() res.json({ - status: "success", + status: 'success', data: { token, - user: userData, - }, - }); + user: userData + } + }) } catch (err) { - next(err); + next(err) } }, getUser: async (req, res, next) => { try { - const { id } = req.params; - const currentUserId = getUser(req).dataValues.id; - console.log(currentUserId); + const { id } = req.params + const currentUserId = getUser(req).dataValues.id + console.log(currentUserId) const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id }, + where: { UserId: id } }), Followship.count({ - where: { followerId: id }, + where: { followerId: id } }), Followship.count({ - where: { followingId: id }, - }), - ]); + where: { followingId: id } + }) + ]) if (!user) { return res .status(401) - .json({ status: "error", message: "This user does not exist" }); + .json({ status: 'error', message: 'This user does not exist' }) } - delete user.password; - user.tweetCount = tweetCount; - user.followerCount = followerCount; - user.followingCount = followingCount; + delete user.password + user.tweetCount = tweetCount + user.followerCount = followerCount + user.followingCount = followingCount if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) user.isFollowed = checkUserFollowing.some( - (follow) => follow.followingId === Number(id) - ); + follow => follow.followingId === Number(id) + ) } - res.status(200).json(user); + res.status(200).json(user) } catch (err) { - next(err); + next(err) } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id; + const userId = req.params.id const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -138,24 +138,24 @@ const userController = { include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ - { model: User, as: "author", attributes: ["account", "name"] }, - ], - }, + { model: User, as: 'author', attributes: ['account', 'name'] } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, - }), - ]); + order: [['createdAt', 'DESC']], + nest: true + }) + ]) - console.log(user, replies); - const userRepliesResult = replies.map((reply) => ({ + console.log(user, replies) + const userRepliesResult = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -165,17 +165,17 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - console.log(userRepliesResult); + console.log(userRepliesResult) - res.status(200).json(userRepliesResult); + res.status(200).json(userRepliesResult) } catch (err) { - console.error(err); - next(err); + console.error(err) + next(err) } - }, -}; + } +} -module.exports = userController; +module.exports = userController diff --git a/routes/index.js b/routes/index.js index d3ec157d5d..6d617007a3 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,90 +1,90 @@ -const express = require("express"); -const router = express.Router(); +const express = require('express') +const router = express.Router() -const admin = require("./modules/admin"); +const admin = require('./modules/admin') -const userController = require("../controllers/apis/user-controller"); -const tweetController = require("../controllers/apis/tweet-controller"); +const userController = require('../controllers/apis/user-controller') +const tweetController = require('../controllers/apis/tweet-controller') -const { apiErrorHandler } = require("../middleware/error-handler"); +const { apiErrorHandler } = require('../middleware/error-handler') const { authenticated, authenticatedAdmin, - authenticatedUser, -} = require("../middleware/api-auth"); + authenticatedUser +} = require('../middleware/api-auth') // api/admin -router.use("/api/admin", authenticated, authenticatedAdmin, admin); +router.use('/api/admin', authenticated, authenticatedAdmin, admin) // api/users // router.get('/api/users', userController.getUsers) -router.post("/api/users", userController.signUp); -router.post("/api/users/signin", userController.signIn); +router.post('/api/users', userController.signUp) +router.post('/api/users/signin', userController.signIn) router.get( - "/api/users/:id/replied_tweets", + '/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies -); +) router.get( - "/api/users/:id", + '/api/users/:id', authenticated, authenticatedUser, userController.getUser -); +) // api/tweets router.get( - "/api/tweets/:tweet_id/replies", + '/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.getReplies -); +) router.post( - "/api/tweets/:tweet_id/replies", + '/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.createReply -); +) router.get( - "/api/tweets/:tweet_id/likes", + '/api/tweets/:tweet_id/likes', authenticated, authenticatedUser, tweetController.getLikes -); +) router.post( - "/api/tweets/:tweet_id/like", + '/api/tweets/:tweet_id/like', authenticated, authenticatedUser, tweetController.likeTweet -); +) router.post( - "/api/tweets/:tweet_id/unlike", + '/api/tweets/:tweet_id/unlike', authenticated, authenticatedUser, tweetController.unlikeTweet -); +) router.get( - "/api/tweets/:tweet_id", + '/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetController.getTweet -); +) router.post( - "/api/tweets", + '/api/tweets', authenticated, authenticatedUser, tweetController.createTweet -); +) router.get( - "/api/tweets", + '/api/tweets', authenticated, authenticatedUser, tweetController.getTweets -); +) -router.use("/", apiErrorHandler); +router.use('/', apiErrorHandler) -module.exports = router; +module.exports = router From 01f46111889762f314de4bbd763e9c08555e3a73 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Fri, 25 Aug 2023 21:45:20 +0800 Subject: [PATCH 055/170] style: formatting --- controllers/apis/tweet-controller.js | 4 +- migrations/20190115071420-create-tweet.js | 9 --- routes/index.js | 77 ++++------------------- routes/modules/admin.js | 6 +- 4 files changed, 14 insertions(+), 82 deletions(-) delete mode 100644 migrations/20190115071420-create-tweet.js diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 7b683dd248..335b97514b 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -69,7 +69,7 @@ const tweetContorller = { ]) if (!tweet) throw new Error("Tweet didn't exist!") if (!like) throw new Error("You haven't liked this tweet!") - const unlike = await Like.destroy({ + await Like.destroy({ where: { userId, tweetId @@ -197,7 +197,7 @@ const tweetContorller = { ] }) ]) - console.log(likes) + // console.log(likes) if (!tweet) throw new Error("Tweet didn't exist!") if (!likes) throw new Error('NO ONE liked this tweet!') const likedData = likes.map(like => ({ diff --git a/migrations/20190115071420-create-tweet.js b/migrations/20190115071420-create-tweet.js deleted file mode 100644 index e436c71f81..0000000000 --- a/migrations/20190115071420-create-tweet.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - up: function (queryInterface, Sequelize) { - return Promise.resolve() - }, - - down: function (queryInterface) { - return Promise.resolve() - } -} diff --git a/routes/index.js b/routes/index.js index 6d617007a3..8ea6d8e390 100644 --- a/routes/index.js +++ b/routes/index.js @@ -7,11 +7,7 @@ const userController = require('../controllers/apis/user-controller') const tweetController = require('../controllers/apis/tweet-controller') const { apiErrorHandler } = require('../middleware/error-handler') -const { - authenticated, - authenticatedAdmin, - authenticatedUser -} = require('../middleware/api-auth') +const { authenticated, authenticatedAdmin, authenticatedUser } = require('../middleware/api-auth') // api/admin router.use('/api/admin', authenticated, authenticatedAdmin, admin) @@ -20,70 +16,19 @@ router.use('/api/admin', authenticated, authenticatedAdmin, admin) // router.get('/api/users', userController.getUsers) router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) -router.get( - '/api/users/:id/replied_tweets', - authenticated, - authenticatedUser, - userController.getUserReplies -) -router.get( - '/api/users/:id', - authenticated, - authenticatedUser, - userController.getUser -) +router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) +router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) // api/tweets -router.get( - '/api/tweets/:tweet_id/replies', - authenticated, - authenticatedUser, - tweetController.getReplies -) -router.post( - '/api/tweets/:tweet_id/replies', - authenticated, - authenticatedUser, - tweetController.createReply -) -router.get( - '/api/tweets/:tweet_id/likes', - authenticated, - authenticatedUser, - tweetController.getLikes -) -router.post( - '/api/tweets/:tweet_id/like', - authenticated, - authenticatedUser, - tweetController.likeTweet -) -router.post( - '/api/tweets/:tweet_id/unlike', - authenticated, - authenticatedUser, - tweetController.unlikeTweet -) - -router.get( - '/api/tweets/:tweet_id', - authenticated, - authenticatedUser, - tweetController.getTweet -) -router.post( - '/api/tweets', - authenticated, - authenticatedUser, - tweetController.createTweet -) -router.get( - '/api/tweets', - authenticated, - authenticatedUser, - tweetController.getTweets -) +router.get('/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.getReplies) +router.post('/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.createReply) +router.get('/api/tweets/:tweet_id/likes', authenticated, authenticatedUser, tweetController.getLikes) +router.post('/api/tweets/:tweet_id/like', authenticated, authenticatedUser, tweetController.likeTweet) +router.post('/api/tweets/:tweet_id/unlike', authenticated, authenticatedUser, tweetController.unlikeTweet) +router.get('/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetController.getTweet) +router.post('/api/tweets', authenticated, authenticatedUser, tweetController.createTweet) +router.get('/api/tweets', authenticated, authenticatedUser, tweetController.getTweets) router.use('/', apiErrorHandler) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index be0eb70a32..a9fe756585 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -3,11 +3,7 @@ const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') const passport = require('passport') -router.post( - '/login', - passport.authenticate('jwt', { session: false }), - adminController.signIn -) +router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) router.get('/users', adminController.getUsers) router.delete('/tweets/:id', adminController.deleteTweet) From e19a2f840766f8f85f31e8f0b4e6be1b35205a3e Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Fri, 25 Aug 2023 23:51:55 +0800 Subject: [PATCH 056/170] bug: putUser is still in the process --- _helpers.js | 2 +- controllers/apis/user-controller.js | 57 ++++++++- helpers/file-helpers.js | 36 ++++++ middleware/multer.js | 4 + package-lock.json | 172 ++++++++++++++++++++++++++-- package.json | 2 + routes/index.js | 6 +- 7 files changed, 265 insertions(+), 14 deletions(-) create mode 100644 helpers/file-helpers.js diff --git a/_helpers.js b/_helpers.js index 4f17063ab8..d83196d1fb 100644 --- a/_helpers.js +++ b/_helpers.js @@ -1,5 +1,5 @@ function getUser (req) { - return req.user || null + return req.user } module.exports = { diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 1afa7fbfa7..c611a18cf6 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,5 +1,8 @@ const bcrypt = require('bcryptjs') const jwt = require('jsonwebtoken') +// const { imgurFileHandler } = require('../../helpers/file-helpers') +// const imgur = require('imgur') + const db = require('../../models') const { getUser } = require('../../_helpers') @@ -85,8 +88,7 @@ const userController = { getUser: async (req, res, next) => { try { const { id } = req.params - const currentUserId = getUser(req).dataValues.id - console.log(currentUserId) + const currentUserId = getUser(req).id const [user, tweetCount, followerCount, followingCount] = await Promise.all([ @@ -175,6 +177,57 @@ const userController = { console.error(err) next(err) } + }, + updateUser: async (req, res, next) => { + try { + const currentUserId = getUser(req).id + if (currentUserId.toString() !== req.params.id) { + throw new Error('Cannot edit other users profile') + } + + const { account, name, email, password, introduction } = req.body + // const files = req.files || '' + if (name && name.length > 50) throw new Error('the length of name should less than 50 characters') + if (introduction && introduction.length > 160) { throw new Error('the length of introduction should less than 160 characters') } + const user = await User.findByPk(req.params.id) + if (!user) { + return res + .status(401) + .json({ status: 'error', message: 'This user does not exist' }) + } + + if (account) { + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') + } + + // const avatar = user.avatar || '' + // const cover = user.cover || '' + + // if (files.avatar) { + // const avatarBuffer = req.files.avatar[0].buffer + // const avatarUrl = await uploadToImgur(avatarBuffer) + // avatar = avatarUrl + // } + + // if (files.cover) { + // const coverBuffer = req.files.cover[0].buffer + // const coverUrl = await uploadToImgur(coverBuffer) + // cover = coverUrl + // } + + await user.update({ + name: name || user.name, + email: email || user.email, + account: account || user.account, + // password: password ? bcrypt.hashSync(password, 10) : user.password, + introduction: introduction || user.introduction + // avatar: , + // cover: + }) + } catch (err) { + next(err) + } } } diff --git a/helpers/file-helpers.js b/helpers/file-helpers.js new file mode 100644 index 0000000000..1003a57c8a --- /dev/null +++ b/helpers/file-helpers.js @@ -0,0 +1,36 @@ +// const fs = require('fs') // 引入 fs 模組 + +// const imgur = require('imgur') +// // const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID +// // imgur.setClientId(IMGUR_CLIENT_ID) + +// const localFileHandler = file => { // file 是 multer 處理完的檔案 +// return new Promise((resolve, reject) => { +// if (!file) return resolve(null) + +// const fileName = `upload/${file.originalname}` + +// return fs.promises.readFile(file.path) +// .then(data => fs.promises.writeFile(fileName, data)) +// .then(() => resolve(`/${fileName}`)) +// .catch(err => reject(err)) +// }) +// } + +// const imgurFileHandler = file => { +// return new Promise((resolve, reject) => { +// if (!file) return resolve(null) + +// return imgur.uploadFile(file.path) +// .then(img => { +// // console.log(img) +// resolve(img?.link || null) // 檢查 img 是否存在 +// }) +// .catch(err => reject(err)) +// }) +// } + +// module.exports = { +// localFileHandler, +// imgurFileHandler +// } diff --git a/middleware/multer.js b/middleware/multer.js index e69de29bb2..71fb05e07f 100644 --- a/middleware/multer.js +++ b/middleware/multer.js @@ -0,0 +1,4 @@ +const multer = require('multer') +const upload = multer({ dest: 'temp/' }) + +module.exports = upload diff --git a/package-lock.json b/package-lock.json index 51ff4a8f7d..4f3e5e4be4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,9 +20,11 @@ "express": "^4.16.4", "express-session": "^1.17.3", "faker": "^5.5.3", + "imgur": "^2.3.0", "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", + "multer": "^1.4.5-lts.1", "mysql2": "^2.3.0", "passport": "^0.4.0", "passport-jwt": "^4.0.1", @@ -33,7 +35,6 @@ "sinon-chai": "^3.3.0" }, "devDependencies": { - "dotenv": "^16.3.1", "eslint-config-standard": "^17.1.0", "proxyquire": "^2.1.3", "sequelize-test-helpers": "^1.4.2", @@ -423,6 +424,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -607,8 +613,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -629,6 +634,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", + "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", + "dependencies": { + "follow-redirects": "^1.14.7" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -705,6 +718,11 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, "node_modules/builtins": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", @@ -714,6 +732,17 @@ "semver": "^7.0.0" } }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -898,7 +927,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -925,6 +953,52 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/config-chain": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", @@ -988,8 +1062,7 @@ "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -1078,7 +1151,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -1145,7 +1217,6 @@ "version": "16.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -2228,6 +2299,25 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2673,6 +2763,31 @@ "node": ">= 4" } }, + "node_modules/imgur": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/imgur/-/imgur-2.3.0.tgz", + "integrity": "sha512-ZAgK0YXHfrR+P1KavYSBRQyr0kSvBFrSYrCAr0Zm8EddAakTn8T5WcdX+NvI6GMvHuzwMePjNvV9sFD4sETIUg==", + "dependencies": { + "axios": "^0.25.0", + "form-data": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/imgur/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -3940,6 +4055,23 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/mysql2": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", @@ -4554,8 +4686,7 @@ "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, "node_modules/prop-types": { "version": "15.8.1", @@ -5323,6 +5454,14 @@ "node": ">= 0.8" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5727,6 +5866,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, "node_modules/uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -6093,6 +6237,14 @@ "node": ">=8" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", diff --git a/package.json b/package.json index cc06fae7e7..7c8ccb5f96 100644 --- a/package.json +++ b/package.json @@ -25,9 +25,11 @@ "express": "^4.16.4", "express-session": "^1.17.3", "faker": "^5.5.3", + "imgur": "^1.0.2", "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", + "multer": "^1.4.3", "mysql2": "^2.3.0", "passport": "^0.4.0", "passport-jwt": "^4.0.1", diff --git a/routes/index.js b/routes/index.js index 8ea6d8e390..6d2af27ca4 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,5 +1,8 @@ const express = require('express') const router = express.Router() +const multer = require('multer') +// const storage = multer.memoryStorage() +// const upload = multer({ storage }) const admin = require('./modules/admin') @@ -13,9 +16,10 @@ const { authenticated, authenticatedAdmin, authenticatedUser } = require('../mid router.use('/api/admin', authenticated, authenticatedAdmin, admin) // api/users -// router.get('/api/users', userController.getUsers) + router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) +// router.put('/api/users/:id', authenticated, authenticatedUser, upload.fields([{ name: 'avatar' }, { name: 'cover' }]), userController.updateUser) router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) From 7fff7e2203ba19a57cf6b7b3889c1036e42bf7cf Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 10:15:55 +0800 Subject: [PATCH 057/170] feat: add draft putUser --- controllers/apis/user-controller.js | 18 +++++++++++++----- routes/index.js | 4 ++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index c611a18cf6..87968220c1 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -191,16 +191,19 @@ const userController = { if (introduction && introduction.length > 160) { throw new Error('the length of introduction should less than 160 characters') } const user = await User.findByPk(req.params.id) if (!user) { - return res - .status(401) - .json({ status: 'error', message: 'This user does not exist' }) + return res.status(401).json({ + status: 'error', + message: 'This user does not exist' + }) } if (account) { if (user.account === account) throw new Error('account 已重複註冊!') - if (user.email === email) throw new Error('email 已重複註冊!') } + if (email) { + if (user.email === email) throw new Error('email 已重複註冊!') + } // const avatar = user.avatar || '' // const cover = user.cover || '' @@ -220,11 +223,16 @@ const userController = { name: name || user.name, email: email || user.email, account: account || user.account, - // password: password ? bcrypt.hashSync(password, 10) : user.password, + password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction // avatar: , // cover: }) + res.status(200).json({ + status: 'success', + message: 'Successfully update user.', + data: user + }) } catch (err) { next(err) } diff --git a/routes/index.js b/routes/index.js index 6d2af27ca4..d6eefb78d5 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,6 +1,6 @@ const express = require('express') const router = express.Router() -const multer = require('multer') +// const multer = require('multer') // const storage = multer.memoryStorage() // const upload = multer({ storage }) @@ -19,7 +19,7 @@ router.use('/api/admin', authenticated, authenticatedAdmin, admin) router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) -// router.put('/api/users/:id', authenticated, authenticatedUser, upload.fields([{ name: 'avatar' }, { name: 'cover' }]), userController.updateUser) +router.put('/api/users/:id', authenticated, authenticatedUser, userController.updateUser) router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) From 0ea48122c4919c0c8639acea8d0419e21ca11c37 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sat, 26 Aug 2023 11:33:15 +0800 Subject: [PATCH 058/170] feat: add controller --- controllers/apis/followship-controller.js | 26 +++++ routes/index.js | 127 +++++++++++++++++----- 2 files changed, 128 insertions(+), 25 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index e69de29bb2..f4eb59fc4c 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -0,0 +1,26 @@ +const db = require("../../models"); +const { User, Tweet, Like, Followship } = db; +const helpers = require("../../_helpers"); + +const followshipController = { + followUser: async (req, res, next) => { + try { + const followedUserId = req.body.id; + const getUser = helpers.getUser(req); + const userId = getUser.id; + // const [user, followship] = await Promise.all([ + // User.findByPk(userId), + // Followship.findOne({ where :followerId= }), + // ]); + res.json({ + status: "success", + }); + } catch (err) { + next(err); + } + }, + unfollowUser: (req, res, next) => {}, + getTop10: (req, res, next) => {}, +}; + +module.exports = followshipController; diff --git a/routes/index.js b/routes/index.js index d6eefb78d5..005533ee65 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,39 +1,116 @@ -const express = require('express') -const router = express.Router() +const express = require("express"); +const router = express.Router(); // const multer = require('multer') // const storage = multer.memoryStorage() // const upload = multer({ storage }) -const admin = require('./modules/admin') +const admin = require("./modules/admin"); -const userController = require('../controllers/apis/user-controller') -const tweetController = require('../controllers/apis/tweet-controller') +const userController = require("../controllers/apis/user-controller"); +const tweetController = require("../controllers/apis/tweet-controller"); +const followshipController = require("../controllers/apis/followship-controller"); -const { apiErrorHandler } = require('../middleware/error-handler') -const { authenticated, authenticatedAdmin, authenticatedUser } = require('../middleware/api-auth') +const { apiErrorHandler } = require("../middleware/error-handler"); +const { + authenticated, + authenticatedAdmin, + authenticatedUser, +} = require("../middleware/api-auth"); // api/admin -router.use('/api/admin', authenticated, authenticatedAdmin, admin) +router.use("/api/admin", authenticated, authenticatedAdmin, admin); // api/users - -router.post('/api/users', userController.signUp) -router.post('/api/users/signin', userController.signIn) -router.put('/api/users/:id', authenticated, authenticatedUser, userController.updateUser) -router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) -router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) +router.post("/api/users", userController.signUp); +router.post("/api/users/signin", userController.signIn); +router.put( + "/api/users/:id", + authenticated, + authenticatedUser, + userController.updateUser +); +router.get( + "/api/users/:id/replied_tweets", + authenticated, + authenticatedUser, + userController.getUserReplies +); +router.get( + "/api/users/:id", + authenticated, + authenticatedUser, + userController.getUser +); // api/tweets +router.get( + "/api/tweets/:tweet_id/replies", + authenticated, + authenticatedUser, + tweetController.getReplies +); +router.post( + "/api/tweets/:tweet_id/replies", + authenticated, + authenticatedUser, + tweetController.createReply +); +router.get( + "/api/tweets/:tweet_id/likes", + authenticated, + authenticatedUser, + tweetController.getLikes +); +router.post( + "/api/tweets/:tweet_id/like", + authenticated, + authenticatedUser, + tweetController.likeTweet +); +router.post( + "/api/tweets/:tweet_id/unlike", + authenticated, + authenticatedUser, + tweetController.unlikeTweet +); +router.get( + "/api/tweets/:tweet_id", + authenticated, + authenticatedUser, + tweetController.getTweet +); +router.post( + "/api/tweets", + authenticated, + authenticatedUser, + tweetController.createTweet +); +router.get( + "/api/tweets", + authenticated, + authenticatedUser, + tweetController.getTweets +); -router.get('/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.getReplies) -router.post('/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.createReply) -router.get('/api/tweets/:tweet_id/likes', authenticated, authenticatedUser, tweetController.getLikes) -router.post('/api/tweets/:tweet_id/like', authenticated, authenticatedUser, tweetController.likeTweet) -router.post('/api/tweets/:tweet_id/unlike', authenticated, authenticatedUser, tweetController.unlikeTweet) -router.get('/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetController.getTweet) -router.post('/api/tweets', authenticated, authenticatedUser, tweetController.createTweet) -router.get('/api/tweets', authenticated, authenticatedUser, tweetController.getTweets) - -router.use('/', apiErrorHandler) +// api/followship +router.delete( + "/api/followships/:following_id", + authenticated, + authenticatedUser, + followshipController.unfollowUser +); +router.get( + "/api/followships/top10", + authenticated, + authenticatedUser, + followshipController.getTop10 +); +router.post( + "/api/followships", + authenticated, + authenticatedUser, + followshipController.followUser +); +router.use("/", apiErrorHandler); -module.exports = router +module.exports = router; From 1d62598bfba20cc0967116b51390466aa3aade99 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sat, 26 Aug 2023 12:18:36 +0800 Subject: [PATCH 059/170] feat: follerUser --- controllers/apis/followship-controller.js | 41 ++++++----- routes/index.js | 84 +++++++++++------------ 2 files changed, 67 insertions(+), 58 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index f4eb59fc4c..1950f1786e 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -1,26 +1,35 @@ -const db = require("../../models"); -const { User, Tweet, Like, Followship } = db; -const helpers = require("../../_helpers"); +const db = require('../../models') +const { User, Followship } = db +const helpers = require('../../_helpers') const followshipController = { followUser: async (req, res, next) => { try { - const followedUserId = req.body.id; - const getUser = helpers.getUser(req); - const userId = getUser.id; - // const [user, followship] = await Promise.all([ - // User.findByPk(userId), - // Followship.findOne({ where :followerId= }), - // ]); + const followedUserId = req.body.id + const getUser = helpers.getUser(req) + const userId = getUser.id + const [user, followship] = await Promise.all([ + User.findByPk(userId), + Followship.findOne({ + where: { followerId: followedUserId, followingId: userId } + }) + ]) + if (!user) throw new Error("User didn't exist!") + if (followship) throw new Error("You've are already followed this user!") + Followship.create({ + followerId: followedUserId, + followingId: userId + }) res.json({ - status: "success", - }); + status: 'success', + message: 'successfully follow user!' + }) } catch (err) { - next(err); + next(err) } }, unfollowUser: (req, res, next) => {}, - getTop10: (req, res, next) => {}, -}; + getTop10: (req, res, next) => {} +} -module.exports = followshipController; +module.exports = followshipController diff --git a/routes/index.js b/routes/index.js index 005533ee65..c010a5ea36 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,116 +1,116 @@ -const express = require("express"); -const router = express.Router(); +const express = require('express') +const router = express.Router() // const multer = require('multer') // const storage = multer.memoryStorage() // const upload = multer({ storage }) -const admin = require("./modules/admin"); +const admin = require('./modules/admin') -const userController = require("../controllers/apis/user-controller"); -const tweetController = require("../controllers/apis/tweet-controller"); -const followshipController = require("../controllers/apis/followship-controller"); +const userController = require('../controllers/apis/user-controller') +const tweetController = require('../controllers/apis/tweet-controller') +const followshipController = require('../controllers/apis/followship-controller') -const { apiErrorHandler } = require("../middleware/error-handler"); +const { apiErrorHandler } = require('../middleware/error-handler') const { authenticated, authenticatedAdmin, - authenticatedUser, -} = require("../middleware/api-auth"); + authenticatedUser +} = require('../middleware/api-auth') // api/admin -router.use("/api/admin", authenticated, authenticatedAdmin, admin); +router.use('/api/admin', authenticated, authenticatedAdmin, admin) // api/users -router.post("/api/users", userController.signUp); -router.post("/api/users/signin", userController.signIn); +router.post('/api/users', userController.signUp) +router.post('/api/users/signin', userController.signIn) router.put( - "/api/users/:id", + '/api/users/:id', authenticated, authenticatedUser, userController.updateUser -); +) router.get( - "/api/users/:id/replied_tweets", + '/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies -); +) router.get( - "/api/users/:id", + '/api/users/:id', authenticated, authenticatedUser, userController.getUser -); +) // api/tweets router.get( - "/api/tweets/:tweet_id/replies", + '/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.getReplies -); +) router.post( - "/api/tweets/:tweet_id/replies", + '/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.createReply -); +) router.get( - "/api/tweets/:tweet_id/likes", + '/api/tweets/:tweet_id/likes', authenticated, authenticatedUser, tweetController.getLikes -); +) router.post( - "/api/tweets/:tweet_id/like", + '/api/tweets/:tweet_id/like', authenticated, authenticatedUser, tweetController.likeTweet -); +) router.post( - "/api/tweets/:tweet_id/unlike", + '/api/tweets/:tweet_id/unlike', authenticated, authenticatedUser, tweetController.unlikeTweet -); +) router.get( - "/api/tweets/:tweet_id", + '/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetController.getTweet -); +) router.post( - "/api/tweets", + '/api/tweets', authenticated, authenticatedUser, tweetController.createTweet -); +) router.get( - "/api/tweets", + '/api/tweets', authenticated, authenticatedUser, tweetController.getTweets -); +) // api/followship router.delete( - "/api/followships/:following_id", + '/api/followships/:following_id', authenticated, authenticatedUser, followshipController.unfollowUser -); +) router.get( - "/api/followships/top10", + '/api/followships/top10', authenticated, authenticatedUser, followshipController.getTop10 -); +) router.post( - "/api/followships", + '/api/followships', authenticated, authenticatedUser, followshipController.followUser -); -router.use("/", apiErrorHandler); +) +router.use('/', apiErrorHandler) -module.exports = router; +module.exports = router From 6571ffacef6da7044cffb0eddaed534d062ff0e8 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sat, 26 Aug 2023 12:30:14 +0800 Subject: [PATCH 060/170] feat: follow and unfollow --- controllers/apis/followship-controller.js | 25 ++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 1950f1786e..5d87eda910 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -28,7 +28,30 @@ const followshipController = { next(err) } }, - unfollowUser: (req, res, next) => {}, + unfollowUser: async (req, res, next) => { + try { + const followedUserId = req.params.following_id + const getUser = helpers.getUser(req) + const userId = getUser.id + const [user, followship] = await Promise.all([ + User.findByPk(userId), + Followship.findOne({ + where: { followerId: followedUserId, followingId: userId } + }) + ]) + if (!user) throw new Error("User didn't exist!") + if (!followship) throw new Error("You haven't followed this user!") + Followship.destroy({ + where: { followerId: followedUserId, followingId: userId } + }) + res.json({ + status: 'success', + message: 'successfully unfollow user!' + }) + } catch (err) { + next(err) + } + }, getTop10: (req, res, next) => {} } From ebe660733fa7797b0b561c5c74ff56a8f54af2b5 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 14:42:14 +0800 Subject: [PATCH 061/170] bug: cannot pass test --- .env.example | 4 +- .gitignore | 6 +- app.js | 5 +- controllers/apis/user-controller.js | 63 +++-- helpers/file-helpers.js | 50 ++-- package-lock.json | 407 ++++++++++++++++++++++++---- routes/index.js | 5 +- 7 files changed, 425 insertions(+), 115 deletions(-) diff --git a/.env.example b/.env.example index 11ab5576d6..203f4fa76a 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,3 @@ -JWT_SECRET= \ No newline at end of file +JWT_SECRET= + +IMGUR_CLIENT_ID= \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4daff23660..b80a1c88b8 100644 --- a/.gitignore +++ b/.gitignore @@ -84,4 +84,8 @@ typings/ .fusebox/ # DynamoDB Local files -.dynamodb/ \ No newline at end of file +.dynamodb/ + +# image upload +temp/ +upload/ \ No newline at end of file diff --git a/app.js b/app.js index b9f893c948..9467e45f70 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,8 @@ if (process.NODE_ENV !== 'production') { require('dotenv').config() } -// require('dotenv').config() + +const path = require('path') const express = require('express') const bodyParser = require('body-parser') const routes = require('./routes') @@ -16,6 +17,8 @@ app.use(bodyParser.json()) app.use(passport.initialize()) app.use(passport.session()) +app.use('/upload', express.static(path.join(__dirname, 'upload'))) + const port = process.env.PORT || 3000 // use helpers.getUser(req) to replace req.user diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 87968220c1..a1b16b3474 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,7 +1,6 @@ const bcrypt = require('bcryptjs') const jwt = require('jsonwebtoken') -// const { imgurFileHandler } = require('../../helpers/file-helpers') -// const imgur = require('imgur') +const { imgurFileHandler } = require('../../helpers/file-helpers') const db = require('../../models') const { getUser } = require('../../_helpers') @@ -180,16 +179,11 @@ const userController = { }, updateUser: async (req, res, next) => { try { - const currentUserId = getUser(req).id - if (currentUserId.toString() !== req.params.id) { - throw new Error('Cannot edit other users profile') - } - + const { id } = req.params const { account, name, email, password, introduction } = req.body - // const files = req.files || '' - if (name && name.length > 50) throw new Error('the length of name should less than 50 characters') - if (introduction && introduction.length > 160) { throw new Error('the length of introduction should less than 160 characters') } - const user = await User.findByPk(req.params.id) + + const user = await User.findByPk(id) + if (!user) { return res.status(401).json({ status: 'error', @@ -197,36 +191,53 @@ const userController = { }) } + const currentUserId = getUser(req).id + + if (!currentUserId) { + throw new Error('Current user ID is missing') + } + console.log(currentUserId, Number(id)) + + if (currentUserId !== Number(id)) { + throw new Error('Cannot edit other users profile') + } + // console.log(currentUserId, Number(id)) + + // console.log('File object:', files) + + if (name && name.length > 50) throw new Error('the length of name should less than 50 characters') + if (introduction && introduction.length > 160) { throw new Error('the length of introduction should less than 160 characters') } + if (account) { + const user = await User.findOne({ where: { account } }) if (user.account === account) throw new Error('account 已重複註冊!') } if (email) { + const user = await User.findOne({ where: { email } }) if (user.email === email) throw new Error('email 已重複註冊!') } - // const avatar = user.avatar || '' - // const cover = user.cover || '' - // if (files.avatar) { - // const avatarBuffer = req.files.avatar[0].buffer - // const avatarUrl = await uploadToImgur(avatarBuffer) - // avatar = avatarUrl - // } + const { files } = req + + let newAvatar = '' + let newCover = '' - // if (files.cover) { - // const coverBuffer = req.files.cover[0].buffer - // const coverUrl = await uploadToImgur(coverBuffer) - // cover = coverUrl - // } + if (files.avatar && files.avatar[0].fieldname === 'avatar') { + newAvatar = await imgurFileHandler(files.avatar[0]) + } + if (files.cover && files.cover[0].fieldname === 'cover') { + newCover = await imgurFileHandler(files.cover[0]) + } await user.update({ name: name || user.name, email: email || user.email, account: account || user.account, password: password ? bcrypt.hashSync(password, 10) : user.password, - introduction: introduction || user.introduction - // avatar: , - // cover: + introduction: introduction || user.introduction, + avatar: newAvatar || user.avatar, + cover: newCover || user.cover }) res.status(200).json({ status: 'success', diff --git a/helpers/file-helpers.js b/helpers/file-helpers.js index 1003a57c8a..25923f41c1 100644 --- a/helpers/file-helpers.js +++ b/helpers/file-helpers.js @@ -1,36 +1,18 @@ -// const fs = require('fs') // 引入 fs 模組 +const imgur = require('imgur') +const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID +imgur.setClientId(IMGUR_CLIENT_ID) -// const imgur = require('imgur') -// // const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID -// // imgur.setClientId(IMGUR_CLIENT_ID) +const imgurFileHandler = file => { + return new Promise((resolve, reject) => { + if (!file) return resolve(null) + return imgur.uploadFile(file.path) + .then(img => { + resolve(img?.link || null) + }) + .catch(err => reject(err)) + }) +} -// const localFileHandler = file => { // file 是 multer 處理完的檔案 -// return new Promise((resolve, reject) => { -// if (!file) return resolve(null) - -// const fileName = `upload/${file.originalname}` - -// return fs.promises.readFile(file.path) -// .then(data => fs.promises.writeFile(fileName, data)) -// .then(() => resolve(`/${fileName}`)) -// .catch(err => reject(err)) -// }) -// } - -// const imgurFileHandler = file => { -// return new Promise((resolve, reject) => { -// if (!file) return resolve(null) - -// return imgur.uploadFile(file.path) -// .then(img => { -// // console.log(img) -// resolve(img?.link || null) // 檢查 img 是否存在 -// }) -// .catch(err => reject(err)) -// }) -// } - -// module.exports = { -// localFileHandler, -// imgurFileHandler -// } +module.exports = { + imgurFileHandler +} diff --git a/package-lock.json b/package-lock.json index 4f3e5e4be4..758c5471f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,11 +20,11 @@ "express": "^4.16.4", "express-session": "^1.17.3", "faker": "^5.5.3", - "imgur": "^2.3.0", + "imgur": "^1.0.2", "jsonwebtoken": "^8.5.1", "method-override": "^3.0.0", "mocha": "^6.0.2", - "multer": "^1.4.5-lts.1", + "multer": "^1.4.3", "mysql2": "^2.3.0", "passport": "^0.4.0", "passport-jwt": "^4.0.1", @@ -248,6 +248,17 @@ "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", @@ -279,6 +290,28 @@ "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==" }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, "node_modules/@types/debug": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", @@ -287,12 +320,25 @@ "@types/ms": "*" } }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -303,6 +349,14 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.2.tgz", "integrity": "sha512-5j/lXt7unfPOUlrKC34HIaedONleyLtwkKggiD/0uuMfT8gg2EOpg0dz4lCD15Ga7muC+1WzJZAjIB9simWd6Q==" }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/validator": { "version": "13.11.1", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", @@ -634,14 +688,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/axios": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", - "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", - "dependencies": { - "follow-redirects": "^1.14.7" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -733,16 +779,38 @@ } }, "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", "dependencies": { - "streamsearch": "^1.1.0" + "dicer": "0.2.5", + "readable-stream": "1.1.x" }, "engines": { - "node": ">=10.16.0" + "node": ">=0.8.0" } }, + "node_modules/busboy/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/busboy/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/busboy/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -751,6 +819,31 @@ "node": ">= 0.8" } }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -899,6 +992,17 @@ "node": ">=6" } }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1115,6 +1219,31 @@ "node": ">=0.10.0" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-eql": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", @@ -1132,6 +1261,14 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, "node_modules/define-properties": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", @@ -1193,6 +1330,39 @@ "node": ">=8" } }, + "node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/dicer/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/dicer/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/dicer/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, "node_modules/diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", @@ -1294,6 +1464,14 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2299,25 +2477,6 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, - "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2506,6 +2665,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -2589,6 +2762,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2695,6 +2892,11 @@ "he": "bin/he" } }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -2710,6 +2912,18 @@ "node": ">= 0.8" } }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -2764,15 +2978,24 @@ } }, "node_modules/imgur": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/imgur/-/imgur-2.3.0.tgz", - "integrity": "sha512-ZAgK0YXHfrR+P1KavYSBRQyr0kSvBFrSYrCAr0Zm8EddAakTn8T5WcdX+NvI6GMvHuzwMePjNvV9sFD4sETIUg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/imgur/-/imgur-1.0.2.tgz", + "integrity": "sha512-bZJkRpa3ReR7lSEzAOjO4PPl9OIDQPuiKoG2aOh36PrTBQCrZL/oTcc6VClyyXEg9O6rEMpsuCloxfhqybpfZA==", "dependencies": { - "axios": "^0.25.0", - "form-data": "^4.0.0" + "commander": "^7.1.0", + "form-data": "^4.0.0", + "got": "^11.8.1" }, + "bin": { + "imgur": "cli.js" + } + }, + "node_modules/imgur/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "engines": { - "node": ">=14" + "node": ">= 10" } }, "node_modules/imgur/node_modules/form-data": { @@ -3318,6 +3541,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3432,6 +3660,14 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3636,6 +3872,14 @@ "get-func-name": "^2.0.0" } }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -3765,6 +4009,14 @@ "node": ">= 0.6" } }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4056,20 +4308,22 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/multer": { - "version": "1.4.5-lts.1", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", - "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", "dependencies": { "append-field": "^1.0.0", - "busboy": "^1.0.0", + "busboy": "^0.2.11", "concat-stream": "^1.5.2", "mkdirp": "^0.5.4", "object-assign": "^4.1.1", + "on-finished": "^2.3.0", "type-is": "^1.6.4", "xtend": "^4.0.0" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 0.10.0" } }, "node_modules/mysql2": { @@ -4219,6 +4473,17 @@ "node": ">=6" } }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/npmlog": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", @@ -4406,6 +4671,14 @@ "node": ">= 0.8.0" } }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -4727,6 +5000,15 @@ "resolve": "^1.11.1" } }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -4770,6 +5052,17 @@ } ] }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/random-bytes": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", @@ -4896,6 +5189,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -4905,6 +5203,17 @@ "node": ">=4" } }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/retry-as-promised": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", @@ -5455,11 +5764,11 @@ } }, "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", "engines": { - "node": ">=10.0.0" + "node": ">=0.8.0" } }, "node_modules/string_decoder": { diff --git a/routes/index.js b/routes/index.js index d6eefb78d5..2e7af043f7 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,8 +1,7 @@ const express = require('express') const router = express.Router() -// const multer = require('multer') // const storage = multer.memoryStorage() -// const upload = multer({ storage }) +const upload = require('../middleware/multer') const admin = require('./modules/admin') @@ -19,7 +18,7 @@ router.use('/api/admin', authenticated, authenticatedAdmin, admin) router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) -router.put('/api/users/:id', authenticated, authenticatedUser, userController.updateUser) +router.put('/api/users/:id', authenticated, authenticatedUser, upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'cover', maxCount: 1 }]), userController.updateUser) router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) From 33c43f600a08450355bb3a6fda437f7b3ee9a767 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 16:40:20 +0800 Subject: [PATCH 062/170] feat: getUserTweets --- controllers/apis/user-controller.js | 37 +++++++++++++++++++++++++++-- routes/index.js | 1 + 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index b3a5a8b3e6..b8a9b6fe67 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -266,8 +266,7 @@ const userController = { { model: User, as: 'author', attributes: ['account', 'name', 'avatar'] } ] } - ], - nest: true + ] }) if (likeTweets.length === 0) throw new Error('the user did not like any tweet') @@ -287,6 +286,40 @@ const userController = { } catch (err) { next(err) } + }, + getUserTweets: async (req, res, next) => { + try { + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') + + const userTweets = await Tweet.findAll({ + where: { userId: id }, + order: [['createdAt', 'DESC']], + include: [ + { + model: User, + as: 'author', + attributes: { exclude: ['password'] } + } + ] + }) + + const userTweetsData = userTweets.map(tweet => ({ + TweetId: tweet.id, + tweetBelongerName: tweet.author.name, + tweetBelongerAccount: tweet.author.account, + tweetBelongerAvatar: tweet.author.avatar, + tweetLikeCount: tweet.likeCount, + tweetReplyCount: tweet.replyCount, + description: tweet.description, + createdAt: tweet.createdAt + })) + + res.json(userTweetsData) + } catch (err) { + next(err) + } } } diff --git a/routes/index.js b/routes/index.js index 7a285c111e..de694137e2 100644 --- a/routes/index.js +++ b/routes/index.js @@ -24,6 +24,7 @@ router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) router.put('/api/users/:id', authenticated, authenticatedUser, upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'cover', maxCount: 1 }]), userController.updateUser) router.get('/api/users/:id/likes', authenticated, authenticatedUser, userController.getUserLikes) +router.get('/api/users/:id/tweets', authenticated, authenticatedUser, userController.getUserTweets) router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) From 9b3d79d481ac9a3c24e227b4a4adb124de1c718e Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 18:04:39 +0800 Subject: [PATCH 063/170] feat: add followship seeder --- routes/index.js | 83 +++---------------- .../20230826093227-followships-seed-file.js | 40 +++++++++ 2 files changed, 52 insertions(+), 71 deletions(-) create mode 100644 seeders/20230826093227-followships-seed-file.js diff --git a/routes/index.js b/routes/index.js index de694137e2..e81cf207eb 100644 --- a/routes/index.js +++ b/routes/index.js @@ -10,11 +10,7 @@ const tweetController = require('../controllers/apis/tweet-controller') const followshipController = require('../controllers/apis/followship-controller') const { apiErrorHandler } = require('../middleware/error-handler') -const { - authenticated, - authenticatedAdmin, - authenticatedUser -} = require('../middleware/api-auth') +const { authenticated, authenticatedAdmin, authenticatedUser } = require('../middleware/api-auth') // api/admin router.use('/api/admin', authenticated, authenticatedAdmin, admin) @@ -29,74 +25,19 @@ router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, us router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) // api/tweets -router.get( - '/api/tweets/:tweet_id/replies', - authenticated, - authenticatedUser, - tweetController.getReplies -) -router.post( - '/api/tweets/:tweet_id/replies', - authenticated, - authenticatedUser, - tweetController.createReply -) -router.get( - '/api/tweets/:tweet_id/likes', - authenticated, - authenticatedUser, - tweetController.getLikes -) -router.post( - '/api/tweets/:tweet_id/like', - authenticated, - authenticatedUser, - tweetController.likeTweet -) -router.post( - '/api/tweets/:tweet_id/unlike', - authenticated, - authenticatedUser, - tweetController.unlikeTweet -) -router.get( - '/api/tweets/:tweet_id', - authenticated, - authenticatedUser, - tweetController.getTweet -) -router.post( - '/api/tweets', - authenticated, - authenticatedUser, - tweetController.createTweet -) -router.get( - '/api/tweets', - authenticated, - authenticatedUser, - tweetController.getTweets -) +router.get('/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.getReplies) +router.post('/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.createReply) +router.get('/api/tweets/:tweet_id/likes', authenticated, authenticatedUser, tweetController.getLikes) +router.post('/api/tweets/:tweet_id/like', authenticated, authenticatedUser, tweetController.likeTweet) +router.post('/api/tweets/:tweet_id/unlike', authenticated, authenticatedUser, tweetController.unlikeTweet) +router.get('/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetController.getTweet) +router.post('/api/tweets', authenticated, authenticatedUser, tweetController.createTweet) +router.get('/api/tweets', authenticated, authenticatedUser, tweetController.getTweets) // api/followship -router.delete( - '/api/followships/:following_id', - authenticated, - authenticatedUser, - followshipController.unfollowUser -) -router.get( - '/api/followships/top10', - authenticated, - authenticatedUser, - followshipController.getTop10 -) -router.post( - '/api/followships', - authenticated, - authenticatedUser, - followshipController.followUser -) +router.delete('/api/followships/:following_id', authenticated, authenticatedUser, followshipController.unfollowUser) +router.get('/api/followships/top10', authenticated, authenticatedUser, followshipController.getTop10) +router.post('/api/followships', authenticated, authenticatedUser, followshipController.followUser) router.use('/', apiErrorHandler) module.exports = router diff --git a/seeders/20230826093227-followships-seed-file.js b/seeders/20230826093227-followships-seed-file.js new file mode 100644 index 0000000000..cb1ca2d878 --- /dev/null +++ b/seeders/20230826093227-followships-seed-file.js @@ -0,0 +1,40 @@ +'use strict' + +module.exports = { + up: async (queryInterface, Sequelize) => { + const users = await queryInterface.sequelize.query( + "SELECT id FROM Users WHERE role <> 'admin'", + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + + const uniqueFollowships = new Set() + const followships = [] + + while (uniqueFollowships.size < 30) { + const followerId = users[Math.floor(Math.random() * users.length)].id + let followingId + + do { + followingId = users[Math.floor(Math.random() * users.length)].id + } while (followerId === followingId) + + const combination = `${followerId}-${followingId}` + + if (!uniqueFollowships.has(combination)) { + uniqueFollowships.add(combination) + followships.push({ + follower_id: followerId, + following_Id: followingId, + created_at: new Date(), + updated_at: new Date() + }) + } + } + + await queryInterface.bulkInsert('Followships', followships) + }, + + down: async (queryInterface, Sequelize) => { + return queryInterface.bulkDelete('Followships', null, {}) + } +} From b20adf2d70735c9491b48a9a748b85a4d1579a29 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 18:33:45 +0800 Subject: [PATCH 064/170] add getUserFollowers --- controllers/apis/user-controller.js | 25 +++++++++++++++++++++++++ models/followship.js | 2 ++ routes/index.js | 1 + 3 files changed, 28 insertions(+) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index b8a9b6fe67..881ca16ba6 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -320,6 +320,31 @@ const userController = { } catch (err) { next(err) } + }, + getUserFollowers: async (req, res, next) => { + try { + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') + + const followers = await Followship.findAll({ + where: { followingId: id }, + order: [['createdAt', 'DESC']], + include: [ + { + model: User, + as: 'follower', + attributes: { exclude: ['password'] } + } + ] + }) + + console.log(followers) + + res.json(followers) + } catch (err) { + next(err) + } } } diff --git a/models/followship.js b/models/followship.js index 97bf78a757..664931f2a6 100644 --- a/models/followship.js +++ b/models/followship.js @@ -9,6 +9,8 @@ module.exports = (sequelize, DataTypes) => { */ static associate (models) { // define association here + Followship.belongsTo(models.User, { foreignKey: 'followerId', as: 'follower' }) + Followship.belongsTo(models.User, { foreignKey: 'followingId', as: 'following' }) } } Followship.init( diff --git a/routes/index.js b/routes/index.js index e81cf207eb..ab868b42de 100644 --- a/routes/index.js +++ b/routes/index.js @@ -20,6 +20,7 @@ router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) router.put('/api/users/:id', authenticated, authenticatedUser, upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'cover', maxCount: 1 }]), userController.updateUser) router.get('/api/users/:id/likes', authenticated, authenticatedUser, userController.getUserLikes) +router.get('/api/users/:id/followers', authenticated, authenticatedUser, userController.getUserFollowers) router.get('/api/users/:id/tweets', authenticated, authenticatedUser, userController.getUserTweets) router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) From b223210ac179ffaeaa22ccce2294aa509fc2bf48 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 21:17:07 +0800 Subject: [PATCH 065/170] fix: to pass getUserFollowers test --- controllers/apis/user-controller.js | 34 +++++++++++++++++++++++++---- routes/index.js | 1 + 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 881ca16ba6..754936344b 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,9 +1,10 @@ const bcrypt = require('bcryptjs') const jwt = require('jsonwebtoken') +const sequelize = require('sequelize') const { imgurFileHandler } = require('../../helpers/file-helpers') const db = require('../../models') -const { getUser } = require('../../_helpers') +const helpers = require('../../_helpers') const { User, Tweet, Reply, Followship, Like } = db const { Op } = require('sequelize') @@ -324,9 +325,12 @@ const userController = { getUserFollowers: async (req, res, next) => { try { const { id } = req.params + // const currentUserId = helpers.getUser(req).id const user = await User.findByPk(id, { raw: true, nest: true }) if (!user) throw new Error('User does not exist') + const currentUserId = helpers.getUser(req).id + const followers = await Followship.findAll({ where: { followingId: id }, order: [['createdAt', 'DESC']], @@ -336,12 +340,34 @@ const userController = { as: 'follower', attributes: { exclude: ['password'] } } - ] + ], + attributes: [ + 'followerId', + 'followingId', + 'createdAt', + 'updatedAt', + [sequelize.literal(`(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)`), 'isFollowed'] + ], + raw: true, + nest: true }) - console.log(followers) + const userFollowersData = followers.map(follower => { + return { + ...follower + } + }) - res.json(followers) + res.status(200).json(userFollowersData) + } catch (err) { + next(err) + } + }, + getUserFollowings: async (req, res, next) => { + try { + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') } catch (err) { next(err) } diff --git a/routes/index.js b/routes/index.js index ab868b42de..9410112ff8 100644 --- a/routes/index.js +++ b/routes/index.js @@ -21,6 +21,7 @@ router.post('/api/users/signin', userController.signIn) router.put('/api/users/:id', authenticated, authenticatedUser, upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'cover', maxCount: 1 }]), userController.updateUser) router.get('/api/users/:id/likes', authenticated, authenticatedUser, userController.getUserLikes) router.get('/api/users/:id/followers', authenticated, authenticatedUser, userController.getUserFollowers) +router.get('/api/users/:id/followings', authenticated, authenticatedUser, userController.getUserFollowings) router.get('/api/users/:id/tweets', authenticated, authenticatedUser, userController.getUserTweets) router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) From 31a46eadea300beebc7afff3cc55ad3ff1a64b22 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 21:45:21 +0800 Subject: [PATCH 066/170] feat: modify cors env --- app.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app.js b/app.js index 9467e45f70..e49025c6c3 100644 --- a/app.js +++ b/app.js @@ -7,9 +7,16 @@ const express = require('express') const bodyParser = require('body-parser') const routes = require('./routes') const passport = require('./config/passport') +const cors = require('cors') const app = express() +const corsOptions = { + origin: 'https://mighty-temple-45104-0d6672fb07d0.herokuapp.com' +} + +app.use(cors(corsOptions)) + // bodyparser設定 app.use(bodyParser.urlencoded({ extended: true })) app.use(bodyParser.json()) From 176945d9bba98fa1040ecfcba6d10870bc22883d Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 22:19:17 +0800 Subject: [PATCH 067/170] feat: add getUserFollowing --- controllers/apis/user-controller.js | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 754936344b..4498267ee5 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -325,7 +325,6 @@ const userController = { getUserFollowers: async (req, res, next) => { try { const { id } = req.params - // const currentUserId = helpers.getUser(req).id const user = await User.findByPk(id, { raw: true, nest: true }) if (!user) throw new Error('User does not exist') @@ -368,6 +367,38 @@ const userController = { const { id } = req.params const user = await User.findByPk(id, { raw: true, nest: true }) if (!user) throw new Error('User does not exist') + const currentUserId = helpers.getUser(req).id + + const following = await Followship.findAll({ + where: { followerId: id }, + order: [['createdAt', 'DESC']], + include: [ + { + model: User, + as: 'following', + attributes: { exclude: ['password'] } + } + ], + attributes: [ + 'followerId', + 'followingId', + 'createdAt', + 'updatedAt', + [sequelize.literal(`(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)`), 'isFollowed'] + ], + raw: true, + nest: true + }) + + const userFollowersData = following.map(follower => { + return { + ...follower + } + }) + console.log(currentUserId) + console.log(id) + + res.status(200).json(userFollowersData) } catch (err) { next(err) } From 97aaab8adf0222797c418036fbd8b9d6f4cec899 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 22:30:23 +0800 Subject: [PATCH 068/170] fix: pass some test --- controllers/apis/user-controller.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 4498267ee5..4c7a972fac 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -88,7 +88,7 @@ const userController = { getUser: async (req, res, next) => { try { const { id } = req.params - const currentUserId = getUser(req).id + const currentUserId = helpers.getUser(req).id const [user, tweetCount, followerCount, followingCount] = await Promise.all([ @@ -192,7 +192,7 @@ const userController = { }) } - const currentUserId = getUser(req).id + const currentUserId = helpers.getUser(req).id if (!currentUserId) { throw new Error('Current user ID is missing') @@ -224,10 +224,10 @@ const userController = { let newAvatar = '' let newCover = '' - if (files.avatar && files.avatar[0].fieldname === 'avatar') { + if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { newAvatar = await imgurFileHandler(files.avatar[0]) } - if (files.cover && files.cover[0].fieldname === 'cover') { + if (files && files.cover && files.cover[0].fieldname === 'cover') { newCover = await imgurFileHandler(files.cover[0]) } @@ -395,8 +395,6 @@ const userController = { ...follower } }) - console.log(currentUserId) - console.log(id) res.status(200).json(userFollowersData) } catch (err) { From 54cd3e1c992ed0cef9b7f0bd7da9fe97715714bb Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 26 Aug 2023 22:39:43 +0800 Subject: [PATCH 069/170] fix: pass all of the test --- controllers/apis/followship-controller.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 5d87eda910..7144d6f21a 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -5,20 +5,20 @@ const helpers = require('../../_helpers') const followshipController = { followUser: async (req, res, next) => { try { - const followedUserId = req.body.id + const followingId = req.body.id const getUser = helpers.getUser(req) const userId = getUser.id const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: followedUserId, followingId: userId } + where: { followerId: userId, followingId } }) ]) if (!user) throw new Error("User didn't exist!") if (followship) throw new Error("You've are already followed this user!") Followship.create({ - followerId: followedUserId, - followingId: userId + followerId: userId, + followingId }) res.json({ status: 'success', @@ -30,19 +30,19 @@ const followshipController = { }, unfollowUser: async (req, res, next) => { try { - const followedUserId = req.params.following_id + const followingId = req.params.following_id const getUser = helpers.getUser(req) const userId = getUser.id const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: followedUserId, followingId: userId } + where: { followerId: userId, followingId } }) ]) if (!user) throw new Error("User didn't exist!") if (!followship) throw new Error("You haven't followed this user!") Followship.destroy({ - where: { followerId: followedUserId, followingId: userId } + where: { followerId: userId, followingId } }) res.json({ status: 'success', From e18f3cd4746132b8ad6e16b00814ae303fcb9a1c Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 13:00:26 +0800 Subject: [PATCH 070/170] feat: top10 user --- controllers/apis/followship-controller.js | 53 ++++++++++++++++++++++- models/user.js | 7 --- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 7144d6f21a..c1b74b5240 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -1,6 +1,7 @@ const db = require('../../models') const { User, Followship } = db const helpers = require('../../_helpers') +const sequelize = require('sequelize') const followshipController = { followUser: async (req, res, next) => { @@ -52,7 +53,57 @@ const followshipController = { next(err) } }, - getTop10: (req, res, next) => {} + getTop10: async (req, res, next) => { + try { + const getUser = helpers.getUser(req) + const currentUserId = getUser.id + if (!currentUserId) throw new Error("User didn't exist!") + + const top10UsersWithFollowStatus = await User.findAll({ + where: { + role: 'user', + id: { [sequelize.Op.not]: currentUserId } + }, + attributes: [ + 'id', + 'account', + 'name', + 'avatar', + [ + sequelize.literal( + '(SELECT COUNT(DISTINCT id) FROM Followships WHERE following_id = User.id)' + ), + 'totalFollowers' + ], + [ + sequelize.literal( + `EXISTS (SELECT 1 FROM Followships WHERE following_id = User.id AND follower_Id = ${currentUserId})` + ), + 'isFollowed' + ] + ], + include: [ + { + model: User, + as: 'Followers', + attributes: [], + through: { attributes: [] } + } + ], + order: [[sequelize.literal('totalFollowers'), 'DESC']], + limit: 10, + subQuery: false, // 避免因查詢多張表造成limit失常 + raw: true, + nest: true + }) + + res.json({ + top10UsersWithFollowStatus + }) + } catch (err) { + next(err) + } + } } module.exports = followshipController diff --git a/models/user.js b/models/user.js index 7d6895e306..bd6dfc6d45 100644 --- a/models/user.js +++ b/models/user.js @@ -11,13 +11,6 @@ module.exports = (sequelize, DataTypes) => { // define association here User.hasMany(models.Tweet, { foreignKey: 'userId', as: 'author' }) User.hasMany(models.Reply, { foreignKey: 'userId', as: 'replier' }) - - // User.belongsTo(models.Tweet, { foreignKey: "userId", as: "likedTweets" }); - // User.belongsTo(models.Tweet, { - // foreignKey: "userId", - // as: "likedReplies", - // }); - User.hasMany(models.Like, { foreignKey: 'userId' }) User.belongsToMany(models.User, { through: models.Followship, From 5031cb26833f10f1291ff1f667e7b49aedfd529f Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 15:13:38 +0800 Subject: [PATCH 071/170] fix: corsOptions --- app.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index e49025c6c3..dbe0ea3ca5 100644 --- a/app.js +++ b/app.js @@ -12,7 +12,9 @@ const cors = require('cors') const app = express() const corsOptions = { - origin: 'https://mighty-temple-45104-0d6672fb07d0.herokuapp.com' + origin: '*', + methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', + allowedHeaders: ['Content-Type', 'Authorization'] } app.use(cors(corsOptions)) From b561b1355bd45cf5c053604b443725dad6dde5f7 Mon Sep 17 00:00:00 2001 From: Eva <122288367+EvvvaHsu@users.noreply.github.com> Date: Sun, 27 Aug 2023 15:44:53 +0800 Subject: [PATCH 072/170] feat: create README.md --- README.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000000..62aeae2a7c --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# Simple Twitter + +## 簡介 + +本專案作為 AC Simple Twitter 的後端 Web API 專案,提供使用者推文、回覆,對喜歡的推文按愛心,追蹤其他使用者等功能。 + +前端畫面請參考:https://github.com/ailsayang999/my-simple-twitter + +## 環境建置 + +使用 Node.js 的 express 作為框架; MySQL Workbench 作為資料庫儲存資料;其他相關套件請見 package.json 檔案 + +## 主要功能 + +### 前台使用者 + +使用者註冊登入後,可查看其他使用者的推文、發佈推文、對喜歡的推文按愛心、回覆某一則推文、觀看其他使用者追蹤以及被追蹤名單,還可以瀏覽推薦追蹤名單。 + +``` +使用者帳號:user1 +使用者email: user1@example.com +使用者密碼:12345678 +``` + +### 後台管理者 + +管理者(admin)可以查看平台內所有使用者的暱稱、帳號、推文總數、被按讚次數、被多少人追蹤以及追蹤了多少人,也能瀏覽所有推文、刪除某一則推文。 +``` +管理者帳號:root +管理者email: root@example.com +管理者密碼:12345678 +``` + +## 檔案執行 + +1. 請先確保 local 端有安裝 Node.js、MySQL Workbench 及 npm。 + +2. 將本專案下載至本地存放後,在專案內新增 temp 和 upload 資料夾(用以管理暫存圖片使用), 再將 .env.example  檔案改名成  .env ,並根據檔案中使用到的環境變數名稱填入相應的資料。 + +3. 在終端機輸入以下指令,一次安裝所有套件 + +``` +npm install +``` +4. 確認與 MySQL workbench 資料庫連線 + +5. 可根據 package.json 中的預設指令執行本檔案 + +6. 若出現以下訊息,代表可正式運作本專案 + +``` +Example app listening on port 3000! +``` + +7. 若需要使用本專案的種子資料,請依序輸入: + +```js + // 生成種子資料 + npx sequelize db:migrate + npx sequelize db:seed:all +``` + +此種子資料會生成假使用者、假推文、假回覆,以及追蹤和按讚等使用者關聯的假資料 + From 26c5dbfba9fa54f916bc4014049e638583d23f70 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 16:15:09 +0800 Subject: [PATCH 073/170] feat: CORS-header --- app.js | 53 +++++----- controllers/apis/followship-controller.js | 114 +++++++++++----------- middleware/CORS-header.js | 18 ++++ 3 files changed, 101 insertions(+), 84 deletions(-) create mode 100644 middleware/CORS-header.js diff --git a/app.js b/app.js index dbe0ea3ca5..91276dbbba 100644 --- a/app.js +++ b/app.js @@ -1,43 +1,42 @@ -if (process.NODE_ENV !== 'production') { - require('dotenv').config() +if (process.NODE_ENV !== "production") { + require("dotenv").config(); } -const path = require('path') -const express = require('express') -const bodyParser = require('body-parser') -const routes = require('./routes') -const passport = require('./config/passport') -const cors = require('cors') +const path = require("path"); +const express = require("express"); +const bodyParser = require("body-parser"); +const routes = require("./routes"); +const passport = require("./config/passport"); +// const cors = require("cors"); +const { CORSHeader } = require("./middleware/CORS-header"); -const app = express() +const app = express(); -const corsOptions = { - origin: '*', - methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', - allowedHeaders: ['Content-Type', 'Authorization'] -} - -app.use(cors(corsOptions)) +// const corsOptions = { +// origin: "https://mighty-temple-45104-0d6672fb07d0.herokuapp.com", +// }; +// app.use(cors(corsOptions)); // bodyparser設定 -app.use(bodyParser.urlencoded({ extended: true })) -app.use(bodyParser.json()) +app.use(bodyParser.urlencoded({ extended: true })); +app.use(bodyParser.json()); // passport 初始化 -app.use(passport.initialize()) -app.use(passport.session()) +app.use(passport.initialize()); +app.use(passport.session()); -app.use('/upload', express.static(path.join(__dirname, 'upload'))) +app.use("/upload", express.static(path.join(__dirname, "upload"))); -const port = process.env.PORT || 3000 +const port = process.env.PORT || 3000; // use helpers.getUser(req) to replace req.user -function authenticated (req, res, next) { +function authenticated(req, res, next) { // passport.authenticate('jwt', { ses... } -app.use(routes) +// app.use(routes); +app.use("/", CORSHeader, routes); -app.get('/', (req, res) => res.send('Hello World!')) -app.listen(port, () => console.log(`Example app listening on port ${port}!`)) +app.get("/", (req, res) => res.send("Hello World!")); +app.listen(port, () => console.log(`Example app listening on port ${port}!`)); -module.exports = app +module.exports = app; diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index c1b74b5240..1116c75de8 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -1,109 +1,109 @@ -const db = require('../../models') -const { User, Followship } = db -const helpers = require('../../_helpers') -const sequelize = require('sequelize') +const db = require("../../models"); +const { User, Followship } = db; +const helpers = require("../../_helpers"); +const sequelize = require("sequelize"); const followshipController = { followUser: async (req, res, next) => { try { - const followingId = req.body.id - const getUser = helpers.getUser(req) - const userId = getUser.id + const followingId = req.body.id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: userId, followingId } - }) - ]) - if (!user) throw new Error("User didn't exist!") - if (followship) throw new Error("You've are already followed this user!") + where: { followerId: userId, followingId }, + }), + ]); + if (!user) throw new Error("User didn't exist!"); + if (followship) throw new Error("You've are already followed this user!"); Followship.create({ followerId: userId, - followingId - }) + followingId, + }); res.json({ - status: 'success', - message: 'successfully follow user!' - }) + status: "success", + message: "successfully follow user!", + }); } catch (err) { - next(err) + next(err); } }, unfollowUser: async (req, res, next) => { try { - const followingId = req.params.following_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const followingId = req.params.following_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: userId, followingId } - }) - ]) - if (!user) throw new Error("User didn't exist!") - if (!followship) throw new Error("You haven't followed this user!") + where: { followerId: userId, followingId }, + }), + ]); + if (!user) throw new Error("User didn't exist!"); + if (!followship) throw new Error("You haven't followed this user!"); Followship.destroy({ - where: { followerId: userId, followingId } - }) + where: { followerId: userId, followingId }, + }); res.json({ - status: 'success', - message: 'successfully unfollow user!' - }) + status: "success", + message: "successfully unfollow user!", + }); } catch (err) { - next(err) + next(err); } }, getTop10: async (req, res, next) => { try { - const getUser = helpers.getUser(req) - const currentUserId = getUser.id - if (!currentUserId) throw new Error("User didn't exist!") + const getUser = helpers.getUser(req); + const currentUserId = getUser.id; + if (!currentUserId) throw new Error("User didn't exist!"); const top10UsersWithFollowStatus = await User.findAll({ where: { - role: 'user', - id: { [sequelize.Op.not]: currentUserId } + role: "user", + id: { [sequelize.Op.not]: currentUserId }, }, attributes: [ - 'id', - 'account', - 'name', - 'avatar', + "id", + "account", + "name", + "avatar", [ sequelize.literal( - '(SELECT COUNT(DISTINCT id) FROM Followships WHERE following_id = User.id)' + "(SELECT COUNT(DISTINCT id) FROM Followships WHERE following_id = User.id)" ), - 'totalFollowers' + "totalFollowers", ], [ sequelize.literal( `EXISTS (SELECT 1 FROM Followships WHERE following_id = User.id AND follower_Id = ${currentUserId})` ), - 'isFollowed' - ] + "isFollowed", + ], ], include: [ { model: User, - as: 'Followers', + as: "Followers", attributes: [], - through: { attributes: [] } - } + through: { attributes: [] }, + }, ], - order: [[sequelize.literal('totalFollowers'), 'DESC']], + order: [[sequelize.literal("totalFollowers"), "DESC"]], limit: 10, subQuery: false, // 避免因查詢多張表造成limit失常 raw: true, - nest: true - }) + nest: true, + }); res.json({ - top10UsersWithFollowStatus - }) + top10UsersWithFollowStatus, + }); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = followshipController +module.exports = followshipController; diff --git a/middleware/CORS-header.js b/middleware/CORS-header.js new file mode 100644 index 0000000000..46bf5cccca --- /dev/null +++ b/middleware/CORS-header.js @@ -0,0 +1,18 @@ +const CORSHeader = (req, res, next) => { + res.header('Access-Control-Allow-Origin', '*') + res.header( + 'Access-Control-Allow-Headers', + 'Origin, X-Requested-With, Content-Type, Accept, Authorization' + ) + if (req.method === 'OPTIONS') { + res.header( + 'Access-Control-Allow-Methods', + 'GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS' + ) + } + return next() +} + +module.exports = { + CORSHeader +} From edc77be4b79db8ebe2042d890d2882123d911fe3 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 16:16:36 +0800 Subject: [PATCH 074/170] fix: es lint --- app.js | 48 ++++----- controllers/apis/followship-controller.js | 114 +++++++++++----------- 2 files changed, 77 insertions(+), 85 deletions(-) diff --git a/app.js b/app.js index 91276dbbba..a8f9d3559d 100644 --- a/app.js +++ b/app.js @@ -1,42 +1,34 @@ -if (process.NODE_ENV !== "production") { - require("dotenv").config(); +if (process.NODE_ENV !== 'production') { + require('dotenv').config() } -const path = require("path"); -const express = require("express"); -const bodyParser = require("body-parser"); -const routes = require("./routes"); -const passport = require("./config/passport"); -// const cors = require("cors"); -const { CORSHeader } = require("./middleware/CORS-header"); +const path = require('path') +const express = require('express') +const bodyParser = require('body-parser') +const routes = require('./routes') +const passport = require('./config/passport') +const { CORSHeader } = require('./middleware/CORS-header') -const app = express(); - -// const corsOptions = { -// origin: "https://mighty-temple-45104-0d6672fb07d0.herokuapp.com", -// }; -// app.use(cors(corsOptions)); +const app = express() // bodyparser設定 -app.use(bodyParser.urlencoded({ extended: true })); -app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })) +app.use(bodyParser.json()) // passport 初始化 -app.use(passport.initialize()); -app.use(passport.session()); +app.use(passport.initialize()) +app.use(passport.session()) -app.use("/upload", express.static(path.join(__dirname, "upload"))); +app.use('/upload', express.static(path.join(__dirname, 'upload'))) -const port = process.env.PORT || 3000; +const port = process.env.PORT || 3000 // use helpers.getUser(req) to replace req.user -function authenticated(req, res, next) { +function authenticated (req, res, next) { // passport.authenticate('jwt', { ses... } -// app.use(routes); -app.use("/", CORSHeader, routes); - -app.get("/", (req, res) => res.send("Hello World!")); -app.listen(port, () => console.log(`Example app listening on port ${port}!`)); +app.use('/', CORSHeader, routes) +app.get('/', (req, res) => res.send('Hello World!')) +app.listen(port, () => console.log(`Example app listening on port ${port}!`)) -module.exports = app; +module.exports = app diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 1116c75de8..c1b74b5240 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -1,109 +1,109 @@ -const db = require("../../models"); -const { User, Followship } = db; -const helpers = require("../../_helpers"); -const sequelize = require("sequelize"); +const db = require('../../models') +const { User, Followship } = db +const helpers = require('../../_helpers') +const sequelize = require('sequelize') const followshipController = { followUser: async (req, res, next) => { try { - const followingId = req.body.id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const followingId = req.body.id + const getUser = helpers.getUser(req) + const userId = getUser.id const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: userId, followingId }, - }), - ]); - if (!user) throw new Error("User didn't exist!"); - if (followship) throw new Error("You've are already followed this user!"); + where: { followerId: userId, followingId } + }) + ]) + if (!user) throw new Error("User didn't exist!") + if (followship) throw new Error("You've are already followed this user!") Followship.create({ followerId: userId, - followingId, - }); + followingId + }) res.json({ - status: "success", - message: "successfully follow user!", - }); + status: 'success', + message: 'successfully follow user!' + }) } catch (err) { - next(err); + next(err) } }, unfollowUser: async (req, res, next) => { try { - const followingId = req.params.following_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const followingId = req.params.following_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: userId, followingId }, - }), - ]); - if (!user) throw new Error("User didn't exist!"); - if (!followship) throw new Error("You haven't followed this user!"); + where: { followerId: userId, followingId } + }) + ]) + if (!user) throw new Error("User didn't exist!") + if (!followship) throw new Error("You haven't followed this user!") Followship.destroy({ - where: { followerId: userId, followingId }, - }); + where: { followerId: userId, followingId } + }) res.json({ - status: "success", - message: "successfully unfollow user!", - }); + status: 'success', + message: 'successfully unfollow user!' + }) } catch (err) { - next(err); + next(err) } }, getTop10: async (req, res, next) => { try { - const getUser = helpers.getUser(req); - const currentUserId = getUser.id; - if (!currentUserId) throw new Error("User didn't exist!"); + const getUser = helpers.getUser(req) + const currentUserId = getUser.id + if (!currentUserId) throw new Error("User didn't exist!") const top10UsersWithFollowStatus = await User.findAll({ where: { - role: "user", - id: { [sequelize.Op.not]: currentUserId }, + role: 'user', + id: { [sequelize.Op.not]: currentUserId } }, attributes: [ - "id", - "account", - "name", - "avatar", + 'id', + 'account', + 'name', + 'avatar', [ sequelize.literal( - "(SELECT COUNT(DISTINCT id) FROM Followships WHERE following_id = User.id)" + '(SELECT COUNT(DISTINCT id) FROM Followships WHERE following_id = User.id)' ), - "totalFollowers", + 'totalFollowers' ], [ sequelize.literal( `EXISTS (SELECT 1 FROM Followships WHERE following_id = User.id AND follower_Id = ${currentUserId})` ), - "isFollowed", - ], + 'isFollowed' + ] ], include: [ { model: User, - as: "Followers", + as: 'Followers', attributes: [], - through: { attributes: [] }, - }, + through: { attributes: [] } + } ], - order: [[sequelize.literal("totalFollowers"), "DESC"]], + order: [[sequelize.literal('totalFollowers'), 'DESC']], limit: 10, subQuery: false, // 避免因查詢多張表造成limit失常 raw: true, - nest: true, - }); + nest: true + }) res.json({ - top10UsersWithFollowStatus, - }); + top10UsersWithFollowStatus + }) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = followshipController; +module.exports = followshipController From bace556067fb51e373f000a3f871248d741c825a Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 16:46:14 +0800 Subject: [PATCH 075/170] fix: response 200 --- controllers/apis/admin-controller.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 22116aa16c..2da360f492 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -10,12 +10,7 @@ const adminController = { const options = { raw: true, attributes: { - exclude: [ - 'email', - 'password', - 'updatedAt', - 'createdAt' - ] + exclude: ['email', 'password', 'updatedAt', 'createdAt'] } } User.findAll(options) @@ -99,13 +94,13 @@ const adminController = { signIn: async (req, res, next) => { try { const { account, password } = req.body - if (!account || !password) throw new Error('Please enter account and password') + if (!account || !password) { throw new Error('Please enter account and password') } const userData = await User.findOne({ where: { account } }) if (!userData) throw new Error('User does not exist') if (userData.role === 'user') throw new Error('user permission denied') - if (!bcrypt.compareSync(password, userData.password)) throw new Error('Incorrect password') + if (!bcrypt.compareSync(password, userData.password)) { throw new Error('Incorrect password') } const payload = { id: userData.id, @@ -115,7 +110,7 @@ const adminController = { const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' }) - res.json({ + return res.status(200).json({ status: 'success', data: { token, From 496b816af6b84a7fd3d91960b867d37663ece199 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sun, 27 Aug 2023 16:54:38 +0800 Subject: [PATCH 076/170] feat: modify --- app.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app.js b/app.js index dbe0ea3ca5..f0e59d20b9 100644 --- a/app.js +++ b/app.js @@ -12,7 +12,7 @@ const cors = require('cors') const app = express() const corsOptions = { - origin: '*', + origin: '*', methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', allowedHeaders: ['Content-Type', 'Authorization'] } @@ -30,11 +30,6 @@ app.use('/upload', express.static(path.join(__dirname, 'upload'))) const port = process.env.PORT || 3000 -// use helpers.getUser(req) to replace req.user -function authenticated (req, res, next) { - // passport.authenticate('jwt', { ses... -} - app.use(routes) app.get('/', (req, res) => res.send('Hello World!')) From bd5e3633cd249cfde73a6f4285ecf01c180c1c22 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 17:17:11 +0800 Subject: [PATCH 077/170] fix: response 200 --- controllers/apis/followship-controller.js | 118 +++---- controllers/apis/reply-controller.js | 0 controllers/apis/tweet-controller.js | 220 ++++++------ controllers/apis/user-controller.js | 390 ++++++++++++---------- 4 files changed, 375 insertions(+), 353 deletions(-) delete mode 100644 controllers/apis/reply-controller.js diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index c1b74b5240..49f956cd55 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -1,109 +1,109 @@ -const db = require('../../models') -const { User, Followship } = db -const helpers = require('../../_helpers') -const sequelize = require('sequelize') +const db = require("../../models"); +const { User, Followship } = db; +const helpers = require("../../_helpers"); +const sequelize = require("sequelize"); const followshipController = { followUser: async (req, res, next) => { try { - const followingId = req.body.id - const getUser = helpers.getUser(req) - const userId = getUser.id + const followingId = req.body.id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: userId, followingId } - }) - ]) - if (!user) throw new Error("User didn't exist!") - if (followship) throw new Error("You've are already followed this user!") + where: { followerId: userId, followingId }, + }), + ]); + if (!user) throw new Error("User didn't exist!"); + if (followship) throw new Error("You've are already followed this user!"); Followship.create({ followerId: userId, - followingId - }) + followingId, + }); res.json({ - status: 'success', - message: 'successfully follow user!' - }) + status: "success", + message: "successfully follow user!", + }); } catch (err) { - next(err) + next(err); } }, unfollowUser: async (req, res, next) => { try { - const followingId = req.params.following_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const followingId = req.params.following_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: userId, followingId } - }) - ]) - if (!user) throw new Error("User didn't exist!") - if (!followship) throw new Error("You haven't followed this user!") + where: { followerId: userId, followingId }, + }), + ]); + if (!user) throw new Error("User didn't exist!"); + if (!followship) throw new Error("You haven't followed this user!"); Followship.destroy({ - where: { followerId: userId, followingId } - }) - res.json({ - status: 'success', - message: 'successfully unfollow user!' - }) + where: { followerId: userId, followingId }, + }); + res.status(200).json({ + status: "success", + message: "successfully unfollow user!", + }); } catch (err) { - next(err) + next(err); } }, getTop10: async (req, res, next) => { try { - const getUser = helpers.getUser(req) - const currentUserId = getUser.id - if (!currentUserId) throw new Error("User didn't exist!") + const getUser = helpers.getUser(req); + const currentUserId = getUser.id; + if (!currentUserId) throw new Error("User didn't exist!"); const top10UsersWithFollowStatus = await User.findAll({ where: { - role: 'user', - id: { [sequelize.Op.not]: currentUserId } + role: "user", + id: { [sequelize.Op.not]: currentUserId }, }, attributes: [ - 'id', - 'account', - 'name', - 'avatar', + "id", + "account", + "name", + "avatar", [ sequelize.literal( - '(SELECT COUNT(DISTINCT id) FROM Followships WHERE following_id = User.id)' + "(SELECT COUNT(DISTINCT id) FROM Followships WHERE following_id = User.id)" ), - 'totalFollowers' + "totalFollowers", ], [ sequelize.literal( `EXISTS (SELECT 1 FROM Followships WHERE following_id = User.id AND follower_Id = ${currentUserId})` ), - 'isFollowed' - ] + "isFollowed", + ], ], include: [ { model: User, - as: 'Followers', + as: "Followers", attributes: [], - through: { attributes: [] } - } + through: { attributes: [] }, + }, ], - order: [[sequelize.literal('totalFollowers'), 'DESC']], + order: [[sequelize.literal("totalFollowers"), "DESC"]], limit: 10, subQuery: false, // 避免因查詢多張表造成limit失常 raw: true, - nest: true - }) + nest: true, + }); - res.json({ - top10UsersWithFollowStatus - }) + res.status(200).json({ + top10UsersWithFollowStatus, + }); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = followshipController +module.exports = followshipController; diff --git a/controllers/apis/reply-controller.js b/controllers/apis/reply-controller.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 335b97514b..8617ef9a85 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,141 +1,143 @@ -const { Tweet, Like, Reply, User } = require('../../models') -const helpers = require('../../_helpers') +const { Tweet, Like, Reply, User } = require("../../models"); +const helpers = require("../../_helpers"); const tweetContorller = { getTweets: async (req, res, next) => { try { const tweets = await Tweet.findAll({ - raw: true - }) - if (!tweets) throw new Error("Tweet didn't exist!") - res.json(tweets) + raw: true, + }); + if (!tweets) throw new Error("Tweet didn't exist!"); + + return res.status(200).json(tweets); } catch (err) { - next(err) + next(err); } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const tweet = await Tweet.findByPk(tweetId) + const tweetId = req.params.tweet_id; + const tweet = await Tweet.findByPk(tweetId); - if (!tweet) throw new Error("Tweet didn't exist!") - res.json(tweet) + if (!tweet) throw new Error("Tweet didn't exist!"); + return res.status(200).json(tweet); } catch (err) { - next(err) + next(err); } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (like) throw new Error('You have liked this tweet!') + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (like) throw new Error("You have liked this tweet!"); const createdLike = await Like.create({ userId, - tweetId - }) - res.json({ - status: 'success', + tweetId, + }); + return res.status(200).json({ + status: "success", data: createdLike, - isLiked: true - }) + isLiked: true, + }); } catch (err) { - next(err) + next(err); } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (!like) throw new Error("You haven't liked this tweet!") + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!like) throw new Error("You haven't liked this tweet!"); await Like.destroy({ where: { userId, - tweetId - } - }) - res.json({ - status: 'success', - isLiked: false - }) + tweetId, + }, + }); + + res.status(200).json({ + status: "success", + isLiked: false, + }); } catch (err) { - next(err) + next(err); } }, createTweet: async (req, res, next) => { try { - const { description } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id - if (!description) throw new Error('文章內容不可為空白') + const { description } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; + if (!description) throw new Error("文章內容不可為空白"); const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create tweet.', - data: createdTweet - }) + status: "success", + message: "Successfully create tweet.", + data: createdTweet, + }); } catch (err) { - next(err) + next(err); } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ { model: User, - as: 'author', - attributes: ['account', 'name', 'avatar'] - } - ] - } + as: "author", + attributes: ["account", "name", "avatar"], + }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true + order: [["createdAt", "DESC"]], + nest: true, // raw: true // 為何設true就無法取資料? - }) + }); - if (!replies) throw new Error('This tweet has no replies') - console.log(replies) - const repliesData = replies.map(reply => ({ + if (!replies) throw new Error("This tweet has no replies"); + console.log(replies); + const repliesData = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -145,78 +147,78 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - res.status(200).json(repliesData) + res.status(200).json(repliesData); } catch (err) { - next(err) + next(err); } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const { comment } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const { comment } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; - if (!comment) throw new Error('回覆內容不可為空白') + if (!comment) throw new Error("回覆內容不可為空白"); const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); - res.json({ - status: 'success', - message: 'successfully created reply', - replyData - }) + res.status(200).json({ + status: "success", + message: "successfully created reply", + replyData, + }); } catch (err) { - next(err) + next(err); } }, getLikes: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId + tweetId, }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ['password', 'introduction', 'cover'] } - } - ] - }) - ]) + attributes: { exclude: ["password", "introduction", "cover"] }, + }, + ], + }), + ]); // console.log(likes) - if (!tweet) throw new Error("Tweet didn't exist!") - if (!likes) throw new Error('NO ONE liked this tweet!') - const likedData = likes.map(like => ({ + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!likes) throw new Error("NO ONE liked this tweet!"); + const likedData = likes.map((like) => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar - })) - res.json({ - status: 'success', - message: 'successfully get all the liked users', - likedData - }) + likedUserAvatar: like.User.avatar, + })); + res.status(200).json({ + status: "success", + message: "successfully get all the liked users", + likedData, + }); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = tweetContorller +module.exports = tweetContorller; diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 4c7a972fac..7a3da2aacb 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,33 +1,33 @@ -const bcrypt = require('bcryptjs') -const jwt = require('jsonwebtoken') -const sequelize = require('sequelize') -const { imgurFileHandler } = require('../../helpers/file-helpers') +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken"); +const sequelize = require("sequelize"); +const { imgurFileHandler } = require("../../helpers/file-helpers"); -const db = require('../../models') -const helpers = require('../../_helpers') +const db = require("../../models"); +const helpers = require("../../_helpers"); -const { User, Tweet, Reply, Followship, Like } = db -const { Op } = require('sequelize') +const { User, Tweet, Reply, Followship, Like } = db; +const { Op } = require("sequelize"); const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body + const { account, name, email, password, checkPassword } = req.body; if (!account || !name || !email || !password || !checkPassword) { - throw new Error('all the blanks are required') + throw new Error("all the blanks are required"); } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }] - } - }) + [Op.or]: [{ email }, { account }], + }, + }); if (user) { - if (user.account === account) throw new Error('account 已重複註冊!') - if (user.email === email) throw new Error('email 已重複註冊!') + if (user.account === account) throw new Error("account 已重複註冊!"); + if (user.email === email) throw new Error("email 已重複註冊!"); } const createdUser = await User.create({ @@ -35,103 +35,103 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: 'https://picsum.photos/100/100', - cover: 'https://picsum.photos/id/237/700/400', - role: 'user', + avatar: "https://picsum.photos/100/100", + cover: "https://picsum.photos/id/237/700/400", + role: "user", createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create user.', - data: createdUser - }) + status: "success", + message: "Successfully create user.", + data: createdUser, + }); } catch (err) { - next(err) + next(err); } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body + const { account, password } = req.body; if (!account || !password) { - throw new Error('Please enter account and password') + throw new Error("Please enter account and password"); } - const user = await User.findOne({ where: { account } }) - if (!user) throw new Error('User does not exist') - if (user.role === 'admin') throw new Error('admin permission denied') + const user = await User.findOne({ where: { account } }); + if (!user) throw new Error("User does not exist"); + if (user.role === "admin") throw new Error("admin permission denied"); if (!bcrypt.compareSync(password, user.password)) { - throw new Error('Incorrect password') + throw new Error("Incorrect password"); } const payload = { id: user.id, account: user.account, - role: user.role - } + role: user.role, + }; const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: '30d' - }) - const userData = user.toJSON() + expiresIn: "30d", + }); + const userData = user.toJSON(); - res.json({ - status: 'success', + res.status(200).json({ + status: "success", data: { token, - user: userData - } - }) + user: userData, + }, + }); } catch (err) { - next(err) + next(err); } }, getUser: async (req, res, next) => { try { - const { id } = req.params - const currentUserId = helpers.getUser(req).id + const { id } = req.params; + const currentUserId = helpers.getUser(req).id; const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id } + where: { UserId: id }, }), Followship.count({ - where: { followerId: id } + where: { followerId: id }, }), Followship.count({ - where: { followingId: id } - }) - ]) + where: { followingId: id }, + }), + ]); if (!user) { return res .status(401) - .json({ status: 'error', message: 'This user does not exist' }) + .json({ status: "error", message: "This user does not exist" }); } - delete user.password - user.tweetCount = tweetCount - user.followerCount = followerCount - user.followingCount = followingCount + delete user.password; + user.tweetCount = tweetCount; + user.followerCount = followerCount; + user.followingCount = followingCount; if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); user.isFollowed = checkUserFollowing.some( - follow => follow.followingId === Number(id) - ) + (follow) => follow.followingId === Number(id) + ); } - res.status(200).json(user) + res.status(200).json(user); } catch (err) { - next(err) + next(err); } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id + const userId = req.params.id; const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -140,24 +140,24 @@ const userController = { include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ - { model: User, as: 'author', attributes: ['account', 'name'] } - ] - } + { model: User, as: "author", attributes: ["account", "name"] }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true - }) - ]) + order: [["createdAt", "DESC"]], + nest: true, + }), + ]); - console.log(user, replies) - const userRepliesResult = replies.map(reply => ({ + console.log(user, replies); + const userRepliesResult = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -167,68 +167,73 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - console.log(userRepliesResult) + console.log(userRepliesResult); - res.status(200).json(userRepliesResult) + res.status(200).json(userRepliesResult); } catch (err) { - console.error(err) - next(err) + console.error(err); + next(err); } }, updateUser: async (req, res, next) => { try { - const { id } = req.params - const { account, name, email, password, introduction } = req.body + const { id } = req.params; + const { account, name, email, password, introduction } = req.body; - const user = await User.findByPk(id) + const user = await User.findByPk(id); if (!user) { return res.status(401).json({ - status: 'error', - message: 'This user does not exist' - }) + status: "error", + message: "This user does not exist", + }); } - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; if (!currentUserId) { - throw new Error('Current user ID is missing') + throw new Error("Current user ID is missing"); } - console.log(currentUserId, Number(id)) + console.log(currentUserId, Number(id)); if (currentUserId !== Number(id)) { - throw new Error('Cannot edit other users profile') + throw new Error("Cannot edit other users profile"); } // console.log(currentUserId, Number(id)) // console.log('File object:', files) - if (name && name.length > 50) throw new Error('the length of name should less than 50 characters') - if (introduction && introduction.length > 160) { throw new Error('the length of introduction should less than 160 characters') } + if (name && name.length > 50) + throw new Error("the length of name should less than 50 characters"); + if (introduction && introduction.length > 160) { + throw new Error( + "the length of introduction should less than 160 characters" + ); + } if (account) { - const user = await User.findOne({ where: { account } }) - if (user.account === account) throw new Error('account 已重複註冊!') + const user = await User.findOne({ where: { account } }); + if (user.account === account) throw new Error("account 已重複註冊!"); } if (email) { - const user = await User.findOne({ where: { email } }) - if (user.email === email) throw new Error('email 已重複註冊!') + const user = await User.findOne({ where: { email } }); + if (user.email === email) throw new Error("email 已重複註冊!"); } - const { files } = req + const { files } = req; - let newAvatar = '' - let newCover = '' + let newAvatar = ""; + let newCover = ""; - if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { - newAvatar = await imgurFileHandler(files.avatar[0]) + if (files && files.avatar && files.avatar[0].fieldname === "avatar") { + newAvatar = await imgurFileHandler(files.avatar[0]); } - if (files && files.cover && files.cover[0].fieldname === 'cover') { - newCover = await imgurFileHandler(files.cover[0]) + if (files && files.cover && files.cover[0].fieldname === "cover") { + newCover = await imgurFileHandler(files.cover[0]); } await user.update({ @@ -238,41 +243,46 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover - }) + cover: newCover || user.cover, + }); res.status(200).json({ - status: 'success', - message: 'Successfully update user.', - data: user - }) + status: "success", + message: "Successfully update user.", + data: user, + }); } catch (err) { - next(err) + next(err); } }, getUserLikes: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); const likeTweets = await Like.findAll({ where: { userId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: Tweet, - as: 'likedTweet', - attributes: { exclude: ['password'] }, + as: "likedTweet", + attributes: { exclude: ["password"] }, include: [ - { model: User, as: 'author', attributes: ['account', 'name', 'avatar'] } - ] - } - ] - }) + { + model: User, + as: "author", + attributes: ["account", "name", "avatar"], + }, + ], + }, + ], + }); - if (likeTweets.length === 0) throw new Error('the user did not like any tweet') + if (likeTweets.length === 0) + throw new Error("the user did not like any tweet"); - const likeTweetsData = likeTweets.map(like => ({ + const likeTweetsData = likeTweets.map((like) => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, @@ -280,33 +290,33 @@ const userController = { tweetLikeCount: like.likedTweet.likeCount, tweetReplyCount: like.likedTweet.replyCount, tweetContent: like.likedTweet.description, - createdAt: like.createdAt - })) + createdAt: like.createdAt, + })); - res.json(likeTweetsData) + res.status(200).json(likeTweetsData); } catch (err) { - next(err) + next(err); } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); const userTweets = await Tweet.findAll({ where: { userId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: User, - as: 'author', - attributes: { exclude: ['password'] } - } - ] - }) + as: "author", + attributes: { exclude: ["password"] }, + }, + ], + }); - const userTweetsData = userTweets.map(tweet => ({ + const userTweetsData = userTweets.map((tweet) => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -314,93 +324,103 @@ const userController = { tweetLikeCount: tweet.likeCount, tweetReplyCount: tweet.replyCount, description: tweet.description, - createdAt: tweet.createdAt - })) + createdAt: tweet.createdAt, + })); - res.json(userTweetsData) + res.status(200).json(userTweetsData); } catch (err) { - next(err) + next(err); } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; const followers = await Followship.findAll({ where: { followingId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: User, - as: 'follower', - attributes: { exclude: ['password'] } - } + as: "follower", + attributes: { exclude: ["password"] }, + }, ], attributes: [ - 'followerId', - 'followingId', - 'createdAt', - 'updatedAt', - [sequelize.literal(`(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)`), 'isFollowed'] + "followerId", + "followingId", + "createdAt", + "updatedAt", + [ + sequelize.literal( + `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` + ), + "isFollowed", + ], ], raw: true, - nest: true - }) + nest: true, + }); - const userFollowersData = followers.map(follower => { + const userFollowersData = followers.map((follower) => { return { - ...follower - } - }) + ...follower, + }; + }); - res.status(200).json(userFollowersData) + res.status(200).json(userFollowersData); } catch (err) { - next(err) + next(err); } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') - const currentUserId = helpers.getUser(req).id + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); + const currentUserId = helpers.getUser(req).id; const following = await Followship.findAll({ where: { followerId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: User, - as: 'following', - attributes: { exclude: ['password'] } - } + as: "following", + attributes: { exclude: ["password"] }, + }, ], attributes: [ - 'followerId', - 'followingId', - 'createdAt', - 'updatedAt', - [sequelize.literal(`(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)`), 'isFollowed'] + "followerId", + "followingId", + "createdAt", + "updatedAt", + [ + sequelize.literal( + `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` + ), + "isFollowed", + ], ], raw: true, - nest: true - }) + nest: true, + }); - const userFollowersData = following.map(follower => { + const userFollowersData = following.map((follower) => { return { - ...follower - } - }) + ...follower, + }; + }); - res.status(200).json(userFollowersData) + res.status(200).json(userFollowersData); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = userController +module.exports = userController; From 691811f22fd7548813316f746dba067fa4d327ae Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 17:58:51 +0800 Subject: [PATCH 078/170] fix: bugs --- controllers/apis/followship-controller.js | 116 +++---- controllers/apis/tweet-controller.js | 210 ++++++------ controllers/apis/user-controller.js | 380 +++++++++++----------- 3 files changed, 352 insertions(+), 354 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 49f956cd55..8f27631529 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -1,109 +1,109 @@ -const db = require("../../models"); -const { User, Followship } = db; -const helpers = require("../../_helpers"); -const sequelize = require("sequelize"); +const db = require('../../models') +const { User, Followship } = db +const helpers = require('../../_helpers') +const sequelize = require('sequelize') const followshipController = { followUser: async (req, res, next) => { try { - const followingId = req.body.id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const followingId = req.body.id + const getUser = helpers.getUser(req) + const userId = getUser.id const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: userId, followingId }, - }), - ]); - if (!user) throw new Error("User didn't exist!"); - if (followship) throw new Error("You've are already followed this user!"); + where: { followerId: userId, followingId } + }) + ]) + if (!user) throw new Error("User didn't exist!") + if (followship) throw new Error("You've are already followed this user!") Followship.create({ followerId: userId, - followingId, - }); + followingId + }) res.json({ - status: "success", - message: "successfully follow user!", - }); + status: 'success', + message: 'successfully follow user!' + }) } catch (err) { - next(err); + next(err) } }, unfollowUser: async (req, res, next) => { try { - const followingId = req.params.following_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const followingId = req.params.following_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [user, followship] = await Promise.all([ User.findByPk(userId), Followship.findOne({ - where: { followerId: userId, followingId }, - }), - ]); - if (!user) throw new Error("User didn't exist!"); - if (!followship) throw new Error("You haven't followed this user!"); + where: { followerId: userId, followingId } + }) + ]) + if (!user) throw new Error("User didn't exist!") + if (!followship) throw new Error("You haven't followed this user!") Followship.destroy({ - where: { followerId: userId, followingId }, - }); + where: { followerId: userId, followingId } + }) res.status(200).json({ - status: "success", - message: "successfully unfollow user!", - }); + status: 'success', + message: 'successfully unfollow user!' + }) } catch (err) { - next(err); + next(err) } }, getTop10: async (req, res, next) => { try { - const getUser = helpers.getUser(req); - const currentUserId = getUser.id; - if (!currentUserId) throw new Error("User didn't exist!"); + const getUser = helpers.getUser(req) + const currentUserId = getUser.id + if (!currentUserId) throw new Error("User didn't exist!") const top10UsersWithFollowStatus = await User.findAll({ where: { - role: "user", - id: { [sequelize.Op.not]: currentUserId }, + role: 'user', + id: { [sequelize.Op.not]: currentUserId } }, attributes: [ - "id", - "account", - "name", - "avatar", + 'id', + 'account', + 'name', + 'avatar', [ sequelize.literal( - "(SELECT COUNT(DISTINCT id) FROM Followships WHERE following_id = User.id)" + '(SELECT COUNT(DISTINCT id) FROM Followships WHERE following_id = User.id)' ), - "totalFollowers", + 'totalFollowers' ], [ sequelize.literal( - `EXISTS (SELECT 1 FROM Followships WHERE following_id = User.id AND follower_Id = ${currentUserId})` + `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE following_id = User.id AND follower_Id = ${currentUserId}) THEN TRUE ELSE FALSE END)` ), - "isFollowed", - ], + 'isFollowed' + ] ], include: [ { model: User, - as: "Followers", + as: 'Followers', attributes: [], - through: { attributes: [] }, - }, + through: { attributes: [] } + } ], - order: [[sequelize.literal("totalFollowers"), "DESC"]], + order: [[sequelize.literal('totalFollowers'), 'DESC']], limit: 10, subQuery: false, // 避免因查詢多張表造成limit失常 raw: true, - nest: true, - }); + nest: true + }) res.status(200).json({ - top10UsersWithFollowStatus, - }); + top10UsersWithFollowStatus + }) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = followshipController; +module.exports = followshipController diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 8617ef9a85..7b4ff70e8b 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,143 +1,143 @@ -const { Tweet, Like, Reply, User } = require("../../models"); -const helpers = require("../../_helpers"); +const { Tweet, Like, Reply, User } = require('../../models') +const helpers = require('../../_helpers') const tweetContorller = { getTweets: async (req, res, next) => { try { const tweets = await Tweet.findAll({ - raw: true, - }); - if (!tweets) throw new Error("Tweet didn't exist!"); + raw: true + }) + if (!tweets) throw new Error("Tweet didn't exist!") - return res.status(200).json(tweets); + return res.status(200).json(tweets) } catch (err) { - next(err); + next(err) } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const tweet = await Tweet.findByPk(tweetId); + const tweetId = req.params.tweet_id + const tweet = await Tweet.findByPk(tweetId) - if (!tweet) throw new Error("Tweet didn't exist!"); - return res.status(200).json(tweet); + if (!tweet) throw new Error("Tweet didn't exist!") + return res.status(200).json(tweet) } catch (err) { - next(err); + next(err) } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (like) throw new Error("You have liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (like) throw new Error('You have liked this tweet!') const createdLike = await Like.create({ userId, - tweetId, - }); + tweetId + }) return res.status(200).json({ - status: "success", + status: 'success', data: createdLike, - isLiked: true, - }); + isLiked: true + }) } catch (err) { - next(err); + next(err) } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!like) throw new Error("You haven't liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (!like) throw new Error("You haven't liked this tweet!") await Like.destroy({ where: { userId, - tweetId, - }, - }); + tweetId + } + }) res.status(200).json({ - status: "success", - isLiked: false, - }); + status: 'success', + isLiked: false + }) } catch (err) { - next(err); + next(err) } }, createTweet: async (req, res, next) => { try { - const { description } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; - if (!description) throw new Error("文章內容不可為空白"); + const { description } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id + if (!description) throw new Error('文章內容不可為空白') const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create tweet.", - data: createdTweet, - }); + status: 'success', + message: 'Successfully create tweet.', + data: createdTweet + }) } catch (err) { - next(err); + next(err) } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ { model: User, - as: "author", - attributes: ["account", "name", "avatar"], - }, - ], - }, + as: 'author', + attributes: ['account', 'name', 'avatar'] + } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, + order: [['createdAt', 'DESC']], + nest: true // raw: true // 為何設true就無法取資料? - }); + }) - if (!replies) throw new Error("This tweet has no replies"); - console.log(replies); - const repliesData = replies.map((reply) => ({ + if (!replies) throw new Error('This tweet has no replies') + console.log(replies) + const repliesData = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -147,78 +147,78 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(repliesData); + res.status(200).json(repliesData) } catch (err) { - next(err); + next(err) } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const { comment } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const { comment } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id - if (!comment) throw new Error("回覆內容不可為空白"); + if (!comment) throw new Error('回覆內容不可為空白') const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "successfully created reply", - replyData, - }); + status: 'success', + message: 'successfully created reply', + replyData + }) } catch (err) { - next(err); + next(err) } }, getLikes: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId, + tweetId }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ["password", "introduction", "cover"] }, - }, - ], - }), - ]); + attributes: { exclude: ['password', 'introduction', 'cover'] } + } + ] + }) + ]) // console.log(likes) - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!likes) throw new Error("NO ONE liked this tweet!"); - const likedData = likes.map((like) => ({ + if (!tweet) throw new Error("Tweet didn't exist!") + if (!likes) throw new Error('NO ONE liked this tweet!') + const likedData = likes.map(like => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar, - })); + likedUserAvatar: like.User.avatar + })) res.status(200).json({ - status: "success", - message: "successfully get all the liked users", - likedData, - }); + status: 'success', + message: 'successfully get all the liked users', + likedData + }) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = tweetContorller; +module.exports = tweetContorller diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 7a3da2aacb..d0d38ec410 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,33 +1,33 @@ -const bcrypt = require("bcryptjs"); -const jwt = require("jsonwebtoken"); -const sequelize = require("sequelize"); -const { imgurFileHandler } = require("../../helpers/file-helpers"); +const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') +const sequelize = require('sequelize') +const { imgurFileHandler } = require('../../helpers/file-helpers') -const db = require("../../models"); -const helpers = require("../../_helpers"); +const db = require('../../models') +const helpers = require('../../_helpers') -const { User, Tweet, Reply, Followship, Like } = db; -const { Op } = require("sequelize"); +const { User, Tweet, Reply, Followship, Like } = db +const { Op } = require('sequelize') const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body; + const { account, name, email, password, checkPassword } = req.body if (!account || !name || !email || !password || !checkPassword) { - throw new Error("all the blanks are required"); + throw new Error('all the blanks are required') } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }], - }, - }); + [Op.or]: [{ email }, { account }] + } + }) if (user) { - if (user.account === account) throw new Error("account 已重複註冊!"); - if (user.email === email) throw new Error("email 已重複註冊!"); + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') } const createdUser = await User.create({ @@ -35,103 +35,103 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: "https://picsum.photos/100/100", - cover: "https://picsum.photos/id/237/700/400", - role: "user", + avatar: 'https://picsum.photos/100/100', + cover: 'https://picsum.photos/id/237/700/400', + role: 'user', createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create user.", - data: createdUser, - }); + status: 'success', + message: 'Successfully create user.', + data: createdUser + }) } catch (err) { - next(err); + next(err) } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body; + const { account, password } = req.body if (!account || !password) { - throw new Error("Please enter account and password"); + throw new Error('Please enter account and password') } - const user = await User.findOne({ where: { account } }); - if (!user) throw new Error("User does not exist"); - if (user.role === "admin") throw new Error("admin permission denied"); + const user = await User.findOne({ where: { account } }) + if (!user) throw new Error('User does not exist') + if (user.role === 'admin') throw new Error('admin permission denied') if (!bcrypt.compareSync(password, user.password)) { - throw new Error("Incorrect password"); + throw new Error('Incorrect password') } const payload = { id: user.id, account: user.account, - role: user.role, - }; + role: user.role + } const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "30d", - }); - const userData = user.toJSON(); + expiresIn: '30d' + }) + const userData = user.toJSON() res.status(200).json({ - status: "success", + status: 'success', data: { token, - user: userData, - }, - }); + user: userData + } + }) } catch (err) { - next(err); + next(err) } }, getUser: async (req, res, next) => { try { - const { id } = req.params; - const currentUserId = helpers.getUser(req).id; + const { id } = req.params + const currentUserId = helpers.getUser(req).id const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id }, + where: { UserId: id } }), Followship.count({ - where: { followerId: id }, + where: { followerId: id } }), Followship.count({ - where: { followingId: id }, - }), - ]); + where: { followingId: id } + }) + ]) if (!user) { return res .status(401) - .json({ status: "error", message: "This user does not exist" }); + .json({ status: 'error', message: 'This user does not exist' }) } - delete user.password; - user.tweetCount = tweetCount; - user.followerCount = followerCount; - user.followingCount = followingCount; + delete user.password + user.tweetCount = tweetCount + user.followerCount = followerCount + user.followingCount = followingCount if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) user.isFollowed = checkUserFollowing.some( - (follow) => follow.followingId === Number(id) - ); + follow => follow.followingId === Number(id) + ) } - res.status(200).json(user); + res.status(200).json(user) } catch (err) { - next(err); + next(err) } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id; + const userId = req.params.id const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -140,24 +140,24 @@ const userController = { include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ - { model: User, as: "author", attributes: ["account", "name"] }, - ], - }, + { model: User, as: 'author', attributes: ['account', 'name'] } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, - }), - ]); + order: [['createdAt', 'DESC']], + nest: true + }) + ]) - console.log(user, replies); - const userRepliesResult = replies.map((reply) => ({ + console.log(user, replies) + const userRepliesResult = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -167,73 +167,72 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - console.log(userRepliesResult); + console.log(userRepliesResult) - res.status(200).json(userRepliesResult); + res.status(200).json(userRepliesResult) } catch (err) { - console.error(err); - next(err); + console.error(err) + next(err) } }, updateUser: async (req, res, next) => { try { - const { id } = req.params; - const { account, name, email, password, introduction } = req.body; + const { id } = req.params + const { account, name, email, password, introduction } = req.body - const user = await User.findByPk(id); + const user = await User.findByPk(id) if (!user) { return res.status(401).json({ - status: "error", - message: "This user does not exist", - }); + status: 'error', + message: 'This user does not exist' + }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id if (!currentUserId) { - throw new Error("Current user ID is missing"); + throw new Error('Current user ID is missing') } - console.log(currentUserId, Number(id)); + console.log(currentUserId, Number(id)) if (currentUserId !== Number(id)) { - throw new Error("Cannot edit other users profile"); + throw new Error('Cannot edit other users profile') } // console.log(currentUserId, Number(id)) // console.log('File object:', files) - if (name && name.length > 50) - throw new Error("the length of name should less than 50 characters"); + if (name && name.length > 50) { throw new Error('the length of name should less than 50 characters') } if (introduction && introduction.length > 160) { throw new Error( - "the length of introduction should less than 160 characters" - ); + 'the length of introduction should less than 160 characters' + ) } if (account) { - const user = await User.findOne({ where: { account } }); - if (user.account === account) throw new Error("account 已重複註冊!"); + const user = await User.findOne({ where: { account } }) + if (user.account === account) throw new Error('account 已重複註冊!') } if (email) { - const user = await User.findOne({ where: { email } }); - if (user.email === email) throw new Error("email 已重複註冊!"); + const user = await User.findOne({ where: { email } }) + if (user.email === email) throw new Error('email 已重複註冊!') } - const { files } = req; + const { files } = req - let newAvatar = ""; - let newCover = ""; + let newAvatar = '' + let newCover = '' - if (files && files.avatar && files.avatar[0].fieldname === "avatar") { - newAvatar = await imgurFileHandler(files.avatar[0]); + if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { + newAvatar = await imgurFileHandler(files.avatar[0]) } - if (files && files.cover && files.cover[0].fieldname === "cover") { - newCover = await imgurFileHandler(files.cover[0]); + if (files && files.cover && files.cover[0].fieldname === 'cover') { + newCover = await imgurFileHandler(files.cover[0]) } await user.update({ @@ -243,46 +242,45 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover, - }); + cover: newCover || user.cover + }) res.status(200).json({ - status: "success", - message: "Successfully update user.", - data: user, - }); + status: 'success', + message: 'Successfully update user.', + data: user + }) } catch (err) { - next(err); + next(err) } }, getUserLikes: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const likeTweets = await Like.findAll({ where: { userId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: Tweet, - as: "likedTweet", - attributes: { exclude: ["password"] }, + as: 'likedTweet', + attributes: { exclude: ['password'] }, include: [ { model: User, - as: "author", - attributes: ["account", "name", "avatar"], - }, - ], - }, - ], - }); + as: 'author', + attributes: ['account', 'name', 'avatar'] + } + ] + } + ] + }) - if (likeTweets.length === 0) - throw new Error("the user did not like any tweet"); + if (likeTweets.length === 0) { throw new Error('the user did not like any tweet') } - const likeTweetsData = likeTweets.map((like) => ({ + const likeTweetsData = likeTweets.map(like => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, @@ -290,33 +288,33 @@ const userController = { tweetLikeCount: like.likedTweet.likeCount, tweetReplyCount: like.likedTweet.replyCount, tweetContent: like.likedTweet.description, - createdAt: like.createdAt, - })); + createdAt: like.createdAt + })) - res.status(200).json(likeTweetsData); + res.status(200).json(likeTweetsData) } catch (err) { - next(err); + next(err) } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const userTweets = await Tweet.findAll({ where: { userId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: User, - as: "author", - attributes: { exclude: ["password"] }, - }, - ], - }); + as: 'author', + attributes: { exclude: ['password'] } + } + ] + }) - const userTweetsData = userTweets.map((tweet) => ({ + const userTweetsData = userTweets.map(tweet => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -324,103 +322,103 @@ const userController = { tweetLikeCount: tweet.likeCount, tweetReplyCount: tweet.replyCount, description: tweet.description, - createdAt: tweet.createdAt, - })); + createdAt: tweet.createdAt + })) - res.status(200).json(userTweetsData); + res.status(200).json(userTweetsData) } catch (err) { - next(err); + next(err) } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id const followers = await Followship.findAll({ where: { followingId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: User, - as: "follower", - attributes: { exclude: ["password"] }, - }, + as: 'follower', + attributes: { exclude: ['password'] } + } ], attributes: [ - "followerId", - "followingId", - "createdAt", - "updatedAt", + 'followerId', + 'followingId', + 'createdAt', + 'updatedAt', [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - "isFollowed", - ], + 'isFollowed' + ] ], raw: true, - nest: true, - }); + nest: true + }) - const userFollowersData = followers.map((follower) => { + const userFollowersData = followers.map(follower => { return { - ...follower, - }; - }); + ...follower + } + }) - res.status(200).json(userFollowersData); + res.status(200).json(userFollowersData) } catch (err) { - next(err); + next(err) } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); - const currentUserId = helpers.getUser(req).id; + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') + const currentUserId = helpers.getUser(req).id const following = await Followship.findAll({ where: { followerId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: User, - as: "following", - attributes: { exclude: ["password"] }, - }, + as: 'following', + attributes: { exclude: ['password'] } + } ], attributes: [ - "followerId", - "followingId", - "createdAt", - "updatedAt", + 'followerId', + 'followingId', + 'createdAt', + 'updatedAt', [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - "isFollowed", - ], + 'isFollowed' + ] ], raw: true, - nest: true, - }); + nest: true + }) - const userFollowersData = following.map((follower) => { + const userFollowersData = following.map(follower => { return { - ...follower, - }; - }); + ...follower + } + }) - res.status(200).json(userFollowersData); + res.status(200).json(userFollowersData) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = userController; +module.exports = userController From d1d12064ee61c410d98cc3542d9720ef0b4feb48 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sun, 27 Aug 2023 22:21:03 +0800 Subject: [PATCH 079/170] fix: fix small bug and delete unnecessary code --- app.js | 16 ++++++--------- controllers/apis/admin-controller.js | 14 ++++--------- controllers/apis/followship-controller.js | 6 +++--- controllers/apis/reply-controller.js | 0 controllers/apis/tweet-controller.js | 20 +++++++++---------- controllers/apis/user-controller.js | 23 ++++++++-------------- middleware/CORS-header.js | 18 +++++++++++++++++ seeders/20230821074916-tweets-seed-file.js | 2 ++ 8 files changed, 51 insertions(+), 48 deletions(-) delete mode 100644 controllers/apis/reply-controller.js create mode 100644 middleware/CORS-header.js diff --git a/app.js b/app.js index f0e59d20b9..66e5b12e44 100644 --- a/app.js +++ b/app.js @@ -7,18 +7,10 @@ const express = require('express') const bodyParser = require('body-parser') const routes = require('./routes') const passport = require('./config/passport') -const cors = require('cors') +const { CORSHeader } = require('./middleware/CORS-header') const app = express() -const corsOptions = { - origin: '*', - methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', - allowedHeaders: ['Content-Type', 'Authorization'] -} - -app.use(cors(corsOptions)) - // bodyparser設定 app.use(bodyParser.urlencoded({ extended: true })) app.use(bodyParser.json()) @@ -30,8 +22,12 @@ app.use('/upload', express.static(path.join(__dirname, 'upload'))) const port = process.env.PORT || 3000 -app.use(routes) +// use helpers.getUser(req) to replace req.user +// function authenticated (req, res, next) { + // passport.authenticate('jwt', { ses... +// } +app.use('/', CORSHeader, routes) app.get('/', (req, res) => res.send('Hello World!')) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 22116aa16c..c296a17036 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -10,12 +10,7 @@ const adminController = { const options = { raw: true, attributes: { - exclude: [ - 'email', - 'password', - 'updatedAt', - 'createdAt' - ] + exclude: ['email', 'password', 'updatedAt', 'createdAt'] } } User.findAll(options) @@ -24,7 +19,6 @@ const adminController = { if (user.introduction) { user.introduction = user.introduction.substring(0, 50) } - console.log(user) }) res.status(200).json(users) }) @@ -99,13 +93,13 @@ const adminController = { signIn: async (req, res, next) => { try { const { account, password } = req.body - if (!account || !password) throw new Error('Please enter account and password') + if (!account || !password) { throw new Error('Please enter account and password') } const userData = await User.findOne({ where: { account } }) if (!userData) throw new Error('User does not exist') if (userData.role === 'user') throw new Error('user permission denied') - if (!bcrypt.compareSync(password, userData.password)) throw new Error('Incorrect password') + if (!bcrypt.compareSync(password, userData.password)) { throw new Error('Incorrect password') } const payload = { id: userData.id, @@ -115,7 +109,7 @@ const adminController = { const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' }) - res.json({ + return res.status(200).json({ status: 'success', data: { token, diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index c1b74b5240..65b416fd09 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -21,7 +21,7 @@ const followshipController = { followerId: userId, followingId }) - res.json({ + res.status(200).json({ status: 'success', message: 'successfully follow user!' }) @@ -45,7 +45,7 @@ const followshipController = { Followship.destroy({ where: { followerId: userId, followingId } }) - res.json({ + res.status(200).json({ status: 'success', message: 'successfully unfollow user!' }) @@ -97,7 +97,7 @@ const followshipController = { nest: true }) - res.json({ + res.status(200).json({ top10UsersWithFollowStatus }) } catch (err) { diff --git a/controllers/apis/reply-controller.js b/controllers/apis/reply-controller.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 335b97514b..dc11b37ee7 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -5,10 +5,11 @@ const tweetContorller = { getTweets: async (req, res, next) => { try { const tweets = await Tweet.findAll({ - raw: true + raw: true, + order: [['createdAt', 'DESC']] }) if (!tweets) throw new Error("Tweet didn't exist!") - res.json(tweets) + res.status(200).json(tweets) } catch (err) { next(err) } @@ -19,7 +20,7 @@ const tweetContorller = { const tweet = await Tweet.findByPk(tweetId) if (!tweet) throw new Error("Tweet didn't exist!") - res.json(tweet) + res.status(200).json(tweet) } catch (err) { next(err) } @@ -44,7 +45,7 @@ const tweetContorller = { userId, tweetId }) - res.json({ + res.status(200).json({ status: 'success', data: createdLike, isLiked: true @@ -75,7 +76,7 @@ const tweetContorller = { tweetId } }) - res.json({ + res.status(200).json({ status: 'success', isLiked: false }) @@ -89,6 +90,7 @@ const tweetContorller = { const getUser = helpers.getUser(req) const userId = getUser.id if (!description) throw new Error('文章內容不可為空白') + if (description.length > 140) throw new Error('文章內容不可超過 140 字') const createdTweet = await Tweet.create({ userId, description, @@ -118,7 +120,6 @@ const tweetContorller = { { model: Tweet, as: 'tweetreply', - include: [ { model: User, @@ -130,7 +131,6 @@ const tweetContorller = { ], order: [['createdAt', 'DESC']], nest: true - // raw: true // 為何設true就無法取資料? }) if (!replies) throw new Error('This tweet has no replies') @@ -169,7 +169,7 @@ const tweetContorller = { updatedAt: new Date() }) - res.json({ + res.status(200).json({ status: 'success', message: 'successfully created reply', replyData @@ -197,7 +197,7 @@ const tweetContorller = { ] }) ]) - // console.log(likes) + if (!tweet) throw new Error("Tweet didn't exist!") if (!likes) throw new Error('NO ONE liked this tweet!') const likedData = likes.map(like => ({ @@ -208,7 +208,7 @@ const tweetContorller = { likedUserAccount: like.User.account, likedUserAvatar: like.User.avatar })) - res.json({ + res.status(200).json({ status: 'success', message: 'successfully get all the liked users', likedData diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 4c7a972fac..1e004fea3e 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -74,7 +74,7 @@ const userController = { }) const userData = user.toJSON() - res.json({ + res.status(200).json({ status: 'success', data: { token, @@ -156,7 +156,6 @@ const userController = { }) ]) - console.log(user, replies) const userRepliesResult = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, @@ -170,11 +169,8 @@ const userController = { tweetBelongerAccount: reply.tweetreply.author.account })) - console.log(userRepliesResult) - res.status(200).json(userRepliesResult) } catch (err) { - console.error(err) next(err) } }, @@ -197,26 +193,23 @@ const userController = { if (!currentUserId) { throw new Error('Current user ID is missing') } - console.log(currentUserId, Number(id)) if (currentUserId !== Number(id)) { throw new Error('Cannot edit other users profile') } - // console.log(currentUserId, Number(id)) - - // console.log('File object:', files) if (name && name.length > 50) throw new Error('the length of name should less than 50 characters') if (introduction && introduction.length > 160) { throw new Error('the length of introduction should less than 160 characters') } if (account) { - const user = await User.findOne({ where: { account } }) - if (user.account === account) throw new Error('account 已重複註冊!') + const userByAccount = await User.findOne({ where: { account }, raw: true, nest: true }) + + if (userByAccount && userByAccount.account === account) throw new Error('account 已重複註冊!') } if (email) { - const user = await User.findOne({ where: { email } }) - if (user.email === email) throw new Error('email 已重複註冊!') + const userByEmail = await User.findOne({ where: { email } }) + if (userByEmail && userByEmail.email === email) throw new Error('email 已重複註冊!') } const { files } = req @@ -283,7 +276,7 @@ const userController = { createdAt: like.createdAt })) - res.json(likeTweetsData) + res.status(200).json(likeTweetsData) } catch (err) { next(err) } @@ -317,7 +310,7 @@ const userController = { createdAt: tweet.createdAt })) - res.json(userTweetsData) + res.status(200).json(userTweetsData) } catch (err) { next(err) } diff --git a/middleware/CORS-header.js b/middleware/CORS-header.js new file mode 100644 index 0000000000..46bf5cccca --- /dev/null +++ b/middleware/CORS-header.js @@ -0,0 +1,18 @@ +const CORSHeader = (req, res, next) => { + res.header('Access-Control-Allow-Origin', '*') + res.header( + 'Access-Control-Allow-Headers', + 'Origin, X-Requested-With, Content-Type, Accept, Authorization' + ) + if (req.method === 'OPTIONS') { + res.header( + 'Access-Control-Allow-Methods', + 'GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS' + ) + } + return next() +} + +module.exports = { + CORSHeader +} diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index a6e28e14f8..8c3979ccc3 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -18,6 +18,8 @@ module.exports = { description: faker.lorem.text(140), created_at: new Date(), updated_at: new Date(), + like_count: faker.random.number(), + reply_count: faker.random.number(), User_id: userData[i].id }) } From ffc35c34a61824e2a437878c7bdcbfd6a8479200 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 22:38:05 +0800 Subject: [PATCH 080/170] fix: bugs --- app.js | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/app.js b/app.js index a8f9d3559d..86f830cf24 100644 --- a/app.js +++ b/app.js @@ -1,34 +1,34 @@ -if (process.NODE_ENV !== 'production') { - require('dotenv').config() +if (process.NODE_ENV !== "production") { + require("dotenv").config(); } -const path = require('path') -const express = require('express') -const bodyParser = require('body-parser') -const routes = require('./routes') -const passport = require('./config/passport') -const { CORSHeader } = require('./middleware/CORS-header') +const path = require("path"); +const express = require("express"); +const bodyParser = require("body-parser"); +const routes = require("./routes"); +const passport = require("./config/passport"); +const { CORSHeader } = require("./middleware/CORS-header"); -const app = express() +const app = express(); // bodyparser設定 -app.use(bodyParser.urlencoded({ extended: true })) -app.use(bodyParser.json()) +app.use(bodyParser.urlencoded({ extended: true })); +app.use(bodyParser.json()); // passport 初始化 -app.use(passport.initialize()) -app.use(passport.session()) +app.use(passport.initialize()); +app.use(passport.session()); -app.use('/upload', express.static(path.join(__dirname, 'upload'))) +app.use("/upload", express.static(path.join(__dirname, "upload"))); -const port = process.env.PORT || 3000 +const port = process.env.PORT || 3000; // use helpers.getUser(req) to replace req.user -function authenticated (req, res, next) { +function authenticated(req, res, next) { // passport.authenticate('jwt', { ses... } -app.use('/', CORSHeader, routes) -app.get('/', (req, res) => res.send('Hello World!')) -app.listen(port, () => console.log(`Example app listening on port ${port}!`)) +app.use("/", CORSHeader, routes); +app.get("/", (req, res) => res.send("Hello World!")); +app.listen(port, () => console.log(`Example app listening on port ${port}!`)); -module.exports = app +module.exports = app; From 49dae7cc155e9fcbe6c6615492bb67dd73f618c4 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 22:46:18 +0800 Subject: [PATCH 081/170] fix: bugs From cd6f82e32bf212ba3b6d7053192454a42a55660d Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 27 Aug 2023 23:10:32 +0800 Subject: [PATCH 082/170] fix: bugs --- app.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app.js b/app.js index 552f5837f4..955c20f77e 100644 --- a/app.js +++ b/app.js @@ -22,12 +22,6 @@ app.use("/upload", express.static(path.join(__dirname, "upload"))); const port = process.env.PORT || 3000; -// use helpers.getUser(req) to replace req.user -// function authenticated (req, res, next) { -// passport.authenticate('jwt', { ses... - -// } - app.use("/", CORSHeader, routes); app.get("/", (req, res) => res.send("Hello World!")); app.listen(port, () => console.log(`Example app listening on port ${port}!`)); From 1f161affd02a763881fa65a48e2b93bd00df62eb Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 00:09:09 +0800 Subject: [PATCH 083/170] fix: likes seed --- app.js | 38 ++++++++++---------- controllers/apis/tweet-controller.js | 2 -- seeders/20230824144658-likes-seed-file.js.js | 30 ++++++++-------- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/app.js b/app.js index 955c20f77e..f817c51610 100644 --- a/app.js +++ b/app.js @@ -1,29 +1,29 @@ -if (process.NODE_ENV !== "production") { - require("dotenv").config(); +if (process.NODE_ENV !== 'production') { + require('dotenv').config() } -const path = require("path"); -const express = require("express"); -const bodyParser = require("body-parser"); -const routes = require("./routes"); -const passport = require("./config/passport"); -const { CORSHeader } = require("./middleware/CORS-header"); +const path = require('path') +const express = require('express') +const bodyParser = require('body-parser') +const routes = require('./routes') +const passport = require('./config/passport') +const { CORSHeader } = require('./middleware/CORS-header') -const app = express(); +const app = express() // bodyparser設定 -app.use(bodyParser.urlencoded({ extended: true })); -app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: true })) +app.use(bodyParser.json()) // passport 初始化 -app.use(passport.initialize()); -app.use(passport.session()); +app.use(passport.initialize()) +app.use(passport.session()) -app.use("/upload", express.static(path.join(__dirname, "upload"))); +app.use('/upload', express.static(path.join(__dirname, 'upload'))) -const port = process.env.PORT || 3000; +const port = process.env.PORT || 3000 -app.use("/", CORSHeader, routes); -app.get("/", (req, res) => res.send("Hello World!")); -app.listen(port, () => console.log(`Example app listening on port ${port}!`)); +app.use('/', CORSHeader, routes) +app.get('/', (req, res) => res.send('Hello World!')) +app.listen(port, () => console.log(`Example app listening on port ${port}!`)) -module.exports = app; +module.exports = app diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 6de4d4e9b6..2630c29e1a 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -22,8 +22,6 @@ const tweetContorller = { if (!tweet) throw new Error("Tweet didn't exist!") res.status(200).json(tweet) - - } catch (err) { next(err) } diff --git a/seeders/20230824144658-likes-seed-file.js.js b/seeders/20230824144658-likes-seed-file.js.js index 26ab44e4a7..196a4633e9 100644 --- a/seeders/20230824144658-likes-seed-file.js.js +++ b/seeders/20230824144658-likes-seed-file.js.js @@ -1,33 +1,33 @@ -'use strict' +"use strict"; module.exports = { up: async (queryInterface, Sequelize) => { const users = await queryInterface.sequelize.query( - 'SELECT id FROM Users WHERE role = "user";', + "SELECT id FROM Users ;", { type: queryInterface.sequelize.QueryTypes.SELECT } - ) + ); const tweets = await queryInterface.sequelize.query( - 'SELECT id FROM Tweets;', + "SELECT id FROM Tweets;", { type: queryInterface.sequelize.QueryTypes.SELECT } - ) + ); - const likes = [] + const likes = []; - tweets.forEach(tweet => { + tweets.forEach((tweet) => { likes.push( ...Array.from({ length: 2 }, () => ({ User_id: users[Math.floor(Math.random() * users.length)].id, Tweet_id: tweet.id, created_at: new Date(), - updated_at: new Date() - }) - )) - }) - await queryInterface.bulkInsert('Likes', likes) + updated_at: new Date(), + })) + ); + }); + await queryInterface.bulkInsert("Likes", likes); }, down: async (queryInterface, Sequelize) => { - return queryInterface.bulkDelete('Likes', null, {}) - } -} + return queryInterface.bulkDelete("Likes", null, {}); + }, +}; From 38e6aed38838662e8577cbbf683d7a62686fa813 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 12:26:51 +0800 Subject: [PATCH 084/170] fix : bugs --- controllers/apis/tweet-controller.js | 214 +++++++++++++-------------- 1 file changed, 107 insertions(+), 107 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 2630c29e1a..419b7232cb 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,144 +1,144 @@ -const { Tweet, Like, Reply, User } = require('../../models') -const helpers = require('../../_helpers') +const { Tweet, Like, Reply, User } = require("../../models"); +const helpers = require("../../_helpers"); const tweetContorller = { getTweets: async (req, res, next) => { try { const tweets = await Tweet.findAll({ raw: true, - order: [['createdAt', 'DESC']] - }) - if (!tweets) throw new Error("Tweet didn't exist!") - res.status(200).json(tweets) + order: [["createdAt", "DESC"]], + }); + if (!tweets) throw new Error("Tweet didn't exist!"); + res.status(200).json(tweets); } catch (err) { - next(err) + next(err); } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const tweet = await Tweet.findByPk(tweetId) + const tweetId = req.params.tweet_id; + const tweet = await Tweet.findByPk(tweetId); - if (!tweet) throw new Error("Tweet didn't exist!") + if (!tweet) throw new Error("Tweet didn't exist!"); - res.status(200).json(tweet) + res.status(200).json(tweet); } catch (err) { - next(err) + next(err); } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (like) throw new Error('You have liked this tweet!') + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (like) throw new Error("You have liked this tweet!"); const createdLike = await Like.create({ userId, - tweetId - }) + tweetId, + }); res.status(200).json({ - - status: 'success', + status: "success", data: createdLike, - isLiked: true - }) + isLiked: true, + }); } catch (err) { - next(err) + next(err); } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (!like) throw new Error("You haven't liked this tweet!") + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!like) throw new Error("You haven't liked this tweet!"); await Like.destroy({ where: { userId, - tweetId - } - }) + tweetId, + }, + }); res.status(200).json({ - status: 'success', - isLiked: false - }) + status: "success", + isLiked: false, + }); } catch (err) { - next(err) + next(err); } }, createTweet: async (req, res, next) => { try { - const { description } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id - if (!description) throw new Error('文章內容不可為空白') - if (description.length > 140) throw new Error('文章內容不可超過 140 字') + const { description } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; + if (!description) throw new Error("文章內容不可為空白"); + if (description.length > 140) throw new Error("文章內容不可超過 140 字"); const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create tweet.', - data: createdTweet - }) + status: "success", + message: "Successfully create tweet.", + data: createdTweet, + }); } catch (err) { - next(err) + next(err); } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ { model: User, - as: 'author', - attributes: ['account', 'name', 'avatar'] - } - ] - } + as: "author", + attributes: ["account", "name", "avatar"], + }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true - }) + order: [["createdAt", "DESC"]], + nest: true, + raw: true, + }); - if (!replies) throw new Error('This tweet has no replies') - console.log(replies) - const repliesData = replies.map(reply => ({ + if (!replies) throw new Error("This tweet has no replies"); + console.log(replies); + const repliesData = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -148,78 +148,78 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - res.status(200).json(repliesData) + res.status(200).json(repliesData); } catch (err) { - next(err) + next(err); } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const { comment } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const { comment } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; - if (!comment) throw new Error('回覆內容不可為空白') + if (!comment) throw new Error("回覆內容不可為空白"); const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'successfully created reply', - replyData - }) + status: "success", + message: "successfully created reply", + replyData, + }); } catch (err) { - next(err) + next(err); } }, getLikes: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId + tweetId, }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ['password', 'introduction', 'cover'] } - } - ] - }) - ]) + attributes: { exclude: ["password", "introduction", "cover"] }, + }, + ], + }), + ]); - if (!tweet) throw new Error("Tweet didn't exist!") - if (!likes) throw new Error('NO ONE liked this tweet!') - const likedData = likes.map(like => ({ + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!likes) throw new Error("NO ONE liked this tweet!"); + const likedData = likes.map((like) => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar - })) + likedUserAvatar: like.User.avatar, + })); res.status(200).json({ - status: 'success', - message: 'successfully get all the liked users', - likedData - }) + status: "success", + message: "successfully get all the liked users", + likedData, + }); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = tweetContorller +module.exports = tweetContorller; From 4503dcecffb3d33a7bfda6033968a2f7bf8372fb Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 13:01:56 +0800 Subject: [PATCH 085/170] feat: modify getTweeets --- controllers/apis/tweet-controller.js | 46 ++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 419b7232cb..b7fa3220cc 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,15 +1,49 @@ const { Tweet, Like, Reply, User } = require("../../models"); const helpers = require("../../_helpers"); +// const defaultLimit = 10 const tweetContorller = { getTweets: async (req, res, next) => { try { - const tweets = await Tweet.findAll({ - raw: true, - order: [["createdAt", "DESC"]], - }); - if (!tweets) throw new Error("Tweet didn't exist!"); - res.status(200).json(tweets); + const getUser = helpers.getUser(req); + const userId = getUser.id; + const options = { + attributes: [ + "id", + "description", + "likeCount", + "replyCount", + "createdAt", + ], + order: [["createdAt", "desc"]], + subQuery: false, + include: [ + { + model: User, + attributes: ["id", "account", "name", "avatar"], + as: "author", + where: { role: "user" }, + }, + { + model: Like, + attributes: ["userId"], + }, + ], + }; + const tweets = await Tweet.findAll(options); + console.log(tweets); + const dataTweets = tweets.map((tweet) => ({ + id: tweet.id, + authorId: tweet.author.id, + authorAccount: tweet.author.account, + authorName: tweet.author.name, + authorAvatar: tweet.author.avatar, + description: tweet.description.substring(0, 140), + likeCount: tweet.likeCount, + replyCount: tweet.replyCount, + isLiked: tweet.Likes.some((i) => i.userId === userId), + })); + res.status(200).json(dataTweets); } catch (err) { next(err); } From 0ba530fa83995fe23bf952b703c3941313b7a559 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 13:47:16 +0800 Subject: [PATCH 086/170] fix: modify admin --- controllers/apis/admin-controller.js | 160 ++++++------ controllers/apis/tweet-controller.js | 246 +++++++++---------- seeders/20230824144658-likes-seed-file.js.js | 28 +-- 3 files changed, 218 insertions(+), 216 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index c296a17036..5a1f9f0840 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -1,105 +1,107 @@ const bcrypt = require('bcryptjs') const db = require('../../models') const { User, Tweet, Like } = db -// const bcrypt = require('bcrypt-nodejs') const jwt = require('jsonwebtoken') const adminController = { - // Admin 取得所有使用者 - getUsers: (req, res) => { - const options = { - raw: true, - attributes: { - exclude: ['email', 'password', 'updatedAt', 'createdAt'] + getUsers: async (req, res, next) => { + try { + const options = { + raw: true, + attributes: { + exclude: ['email', 'password', 'updatedAt', 'createdAt'] + } } - } - User.findAll(options) - .then(users => { - users.forEach(user => { - if (user.introduction) { - user.introduction = user.introduction.substring(0, 50) - } - }) - res.status(200).json(users) - }) - .catch(error => { - res.status(500).json({ - status: 'error', - message: error - }) - }) - }, - // Admin取得所有貼文 - getTweets: (req, res) => { - const options = { - raw: true, - nest: true, - attributes: ['id', 'description', 'replyCount', 'likeCount', 'createdAt'], - include: [ - { - model: User, - attributes: ['id', 'account', 'name', 'avatar'], - as: 'author' + const users = await User.findAll(options) + + users.forEach(user => { + if (user.introduction) { + user.introduction = user.introduction.substring(0, 50) } - ] - } - return Tweet.findAll(options) - .then(tweets => { - tweets.forEach(tweet => { - tweet.description = tweet.description.substring(0, 50) - }) - return res.status(200).json(tweets) }) - .catch(() => - res.status(500).json({ - status: 'error', - message: 'errorrr' - }) - ) + + res.status(200).json(users) + } catch (error) { + next(error) + } }, - // Admin刪除一篇貼文 - deleteTweet: (req, res) => { - return Promise.all([ - Tweet.destroy({ - where: { id: req.params.id }, - raw: true, - nest: true - }), - Like.destroy({ - where: { TweetId: req.params.id }, + getTweets: async (req, res, next) => { + try { + const options = { raw: true, - nest: true + nest: true, + attributes: [ + 'id', + 'description', + 'replyCount', + 'likeCount', + 'createdAt' + ], + include: [ + { + model: User, + attributes: ['id', 'account', 'name', 'avatar'], + as: 'author' + } + ] + } + const tweets = await Tweet.findAll(options) + tweets.forEach(tweet => { + tweet.description = tweet.description.substring(0, 50) }) - ]) - .then(tweet => { - if (!tweet) { - throw new Error( - '此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除' - ) - } - return res.status(200).json({ - status: 'success', - message: 'Successfully delete tweet.' + res.status(200).json(tweets) + } catch (err) { + next(err) + } + }, + + deleteTweet: async (req, res) => { + try { + const [tweet] = await Promise.all([ + Tweet.destroy({ + where: { id: req.params.id }, + raw: true, + nest: true + }), + Like.destroy({ + where: { TweetId: req.params.id }, + raw: true, + nest: true }) + ]) + + if (!tweet) { + throw new Error( + '此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除' + ) + } + + return res.status(200).json({ + status: 'success', + message: 'Successfully delete tweet.' }) - .catch(() => - res.status(500).json({ - status: 'error', - message: 'error' - }) - ) + } catch (error) { + return res.status(500).json({ + status: 'error', + message: error.message + }) + } }, - // Admin 登入 + signIn: async (req, res, next) => { try { const { account, password } = req.body - if (!account || !password) { throw new Error('Please enter account and password') } + if (!account || !password) { + throw new Error('Please enter account and password') + } const userData = await User.findOne({ where: { account } }) if (!userData) throw new Error('User does not exist') if (userData.role === 'user') throw new Error('user permission denied') - if (!bcrypt.compareSync(password, userData.password)) { throw new Error('Incorrect password') } + if (!bcrypt.compareSync(password, userData.password)) { + throw new Error('Incorrect password') + } const payload = { id: userData.id, diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index b7fa3220cc..c9053a94ed 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,38 +1,38 @@ -const { Tweet, Like, Reply, User } = require("../../models"); -const helpers = require("../../_helpers"); +const { Tweet, Like, Reply, User } = require('../../models') +const helpers = require('../../_helpers') // const defaultLimit = 10 const tweetContorller = { getTweets: async (req, res, next) => { try { - const getUser = helpers.getUser(req); - const userId = getUser.id; + const getUser = helpers.getUser(req) + const userId = getUser.id const options = { attributes: [ - "id", - "description", - "likeCount", - "replyCount", - "createdAt", + 'id', + 'description', + 'likeCount', + 'replyCount', + 'createdAt' ], - order: [["createdAt", "desc"]], + order: [['createdAt', 'desc']], subQuery: false, include: [ { model: User, - attributes: ["id", "account", "name", "avatar"], - as: "author", - where: { role: "user" }, + attributes: ['id', 'account', 'name', 'avatar'], + as: 'author', + where: { role: 'user' } }, { model: Like, - attributes: ["userId"], - }, - ], - }; - const tweets = await Tweet.findAll(options); - console.log(tweets); - const dataTweets = tweets.map((tweet) => ({ + attributes: ['userId'] + } + ] + } + const tweets = await Tweet.findAll(options) + console.log(tweets) + const dataTweets = tweets.map(tweet => ({ id: tweet.id, authorId: tweet.author.id, authorAccount: tweet.author.account, @@ -41,138 +41,138 @@ const tweetContorller = { description: tweet.description.substring(0, 140), likeCount: tweet.likeCount, replyCount: tweet.replyCount, - isLiked: tweet.Likes.some((i) => i.userId === userId), - })); - res.status(200).json(dataTweets); + isLiked: tweet.Likes.some(i => i.userId === userId) + })) + res.status(200).json(dataTweets) } catch (err) { - next(err); + next(err) } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const tweet = await Tweet.findByPk(tweetId); + const tweetId = req.params.tweet_id + const tweet = await Tweet.findByPk(tweetId) - if (!tweet) throw new Error("Tweet didn't exist!"); + if (!tweet) throw new Error("Tweet didn't exist!") - res.status(200).json(tweet); + res.status(200).json(tweet) } catch (err) { - next(err); + next(err) } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (like) throw new Error("You have liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (like) throw new Error('You have liked this tweet!') const createdLike = await Like.create({ userId, - tweetId, - }); + tweetId + }) res.status(200).json({ - status: "success", + status: 'success', data: createdLike, - isLiked: true, - }); + isLiked: true + }) } catch (err) { - next(err); + next(err) } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!like) throw new Error("You haven't liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (!like) throw new Error("You haven't liked this tweet!") await Like.destroy({ where: { userId, - tweetId, - }, - }); + tweetId + } + }) res.status(200).json({ - status: "success", - isLiked: false, - }); + status: 'success', + isLiked: false + }) } catch (err) { - next(err); + next(err) } }, createTweet: async (req, res, next) => { try { - const { description } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; - if (!description) throw new Error("文章內容不可為空白"); - if (description.length > 140) throw new Error("文章內容不可超過 140 字"); + const { description } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id + if (!description) throw new Error('文章內容不可為空白') + if (description.length > 140) throw new Error('文章內容不可超過 140 字') const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create tweet.", - data: createdTweet, - }); + status: 'success', + message: 'Successfully create tweet.', + data: createdTweet + }) } catch (err) { - next(err); + next(err) } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ { model: User, - as: "author", - attributes: ["account", "name", "avatar"], - }, - ], - }, + as: 'author', + attributes: ['account', 'name', 'avatar'] + } + ] + } ], - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], nest: true, - raw: true, - }); + raw: true + }) - if (!replies) throw new Error("This tweet has no replies"); - console.log(replies); - const repliesData = replies.map((reply) => ({ + if (!replies) throw new Error('This tweet has no replies') + console.log(replies) + const repliesData = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -182,78 +182,78 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(repliesData); + res.status(200).json(repliesData) } catch (err) { - next(err); + next(err) } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const { comment } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const { comment } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id - if (!comment) throw new Error("回覆內容不可為空白"); + if (!comment) throw new Error('回覆內容不可為空白') const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "successfully created reply", - replyData, - }); + status: 'success', + message: 'successfully created reply', + replyData + }) } catch (err) { - next(err); + next(err) } }, getLikes: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId, + tweetId }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ["password", "introduction", "cover"] }, - }, - ], - }), - ]); + attributes: { exclude: ['password', 'introduction', 'cover'] } + } + ] + }) + ]) - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!likes) throw new Error("NO ONE liked this tweet!"); - const likedData = likes.map((like) => ({ + if (!tweet) throw new Error("Tweet didn't exist!") + if (!likes) throw new Error('NO ONE liked this tweet!') + const likedData = likes.map(like => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar, - })); + likedUserAvatar: like.User.avatar + })) res.status(200).json({ - status: "success", - message: "successfully get all the liked users", - likedData, - }); + status: 'success', + message: 'successfully get all the liked users', + likedData + }) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = tweetContorller; +module.exports = tweetContorller diff --git a/seeders/20230824144658-likes-seed-file.js.js b/seeders/20230824144658-likes-seed-file.js.js index 196a4633e9..4d16a93ab9 100644 --- a/seeders/20230824144658-likes-seed-file.js.js +++ b/seeders/20230824144658-likes-seed-file.js.js @@ -1,33 +1,33 @@ -"use strict"; +'use strict' module.exports = { up: async (queryInterface, Sequelize) => { const users = await queryInterface.sequelize.query( - "SELECT id FROM Users ;", + 'SELECT id FROM Users ;', { type: queryInterface.sequelize.QueryTypes.SELECT } - ); + ) const tweets = await queryInterface.sequelize.query( - "SELECT id FROM Tweets;", + 'SELECT id FROM Tweets;', { type: queryInterface.sequelize.QueryTypes.SELECT } - ); + ) - const likes = []; + const likes = [] - tweets.forEach((tweet) => { + tweets.forEach(tweet => { likes.push( ...Array.from({ length: 2 }, () => ({ User_id: users[Math.floor(Math.random() * users.length)].id, Tweet_id: tweet.id, created_at: new Date(), - updated_at: new Date(), + updated_at: new Date() })) - ); - }); - await queryInterface.bulkInsert("Likes", likes); + ) + }) + await queryInterface.bulkInsert('Likes', likes) }, down: async (queryInterface, Sequelize) => { - return queryInterface.bulkDelete("Likes", null, {}); - }, -}; + return queryInterface.bulkDelete('Likes', null, {}) + } +} From 6e9961821dc8515f1fb45dcd95e2df05cf59aefe Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 14:49:01 +0800 Subject: [PATCH 087/170] fix: getUser modify response --- controllers/apis/admin-controller.js | 121 ++++----- controllers/apis/user-controller.js | 382 ++++++++++++++------------- 2 files changed, 257 insertions(+), 246 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 5a1f9f0840..2665363243 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -1,7 +1,7 @@ -const bcrypt = require('bcryptjs') -const db = require('../../models') -const { User, Tweet, Like } = db -const jwt = require('jsonwebtoken') +const bcrypt = require("bcryptjs"); +const db = require("../../models"); +const { User, Tweet, Like } = db; +const jwt = require("jsonwebtoken"); const adminController = { getUsers: async (req, res, next) => { @@ -9,20 +9,21 @@ const adminController = { const options = { raw: true, attributes: { - exclude: ['email', 'password', 'updatedAt', 'createdAt'] - } - } - const users = await User.findAll(options) - - users.forEach(user => { + exclude: ["email", "password", "updatedAt", "createdAt"], + }, + }; + const users = await User.findAll(options); + // console.log("usersbeforeforeach", users); + users.forEach((user) => { if (user.introduction) { - user.introduction = user.introduction.substring(0, 50) + user.introduction = user.introduction.substring(0, 50); } - }) + }); - res.status(200).json(users) + // console.log(users); + res.status(200).json(users); } catch (error) { - next(error) + next(error); } }, getTweets: async (req, res, next) => { @@ -31,27 +32,27 @@ const adminController = { raw: true, nest: true, attributes: [ - 'id', - 'description', - 'replyCount', - 'likeCount', - 'createdAt' + "id", + "description", + "replyCount", + "likeCount", + "createdAt", ], include: [ { model: User, - attributes: ['id', 'account', 'name', 'avatar'], - as: 'author' - } - ] - } - const tweets = await Tweet.findAll(options) - tweets.forEach(tweet => { - tweet.description = tweet.description.substring(0, 50) - }) - res.status(200).json(tweets) + attributes: ["id", "account", "name", "avatar"], + as: "author", + }, + ], + }; + const tweets = await Tweet.findAll(options); + tweets.forEach((tweet) => { + tweet.description = tweet.description.substring(0, 50); + }); + res.status(200).json(tweets); } catch (err) { - next(err) + next(err); } }, @@ -61,67 +62,67 @@ const adminController = { Tweet.destroy({ where: { id: req.params.id }, raw: true, - nest: true + nest: true, }), Like.destroy({ where: { TweetId: req.params.id }, raw: true, - nest: true - }) - ]) + nest: true, + }), + ]); if (!tweet) { throw new Error( - '此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除' - ) + "此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除" + ); } return res.status(200).json({ - status: 'success', - message: 'Successfully delete tweet.' - }) + status: "success", + message: "Successfully delete tweet.", + }); } catch (error) { return res.status(500).json({ - status: 'error', - message: error.message - }) + status: "error", + message: error.message, + }); } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body + const { account, password } = req.body; if (!account || !password) { - throw new Error('Please enter account and password') + throw new Error("Please enter account and password"); } - const userData = await User.findOne({ where: { account } }) + const userData = await User.findOne({ where: { account } }); - if (!userData) throw new Error('User does not exist') - if (userData.role === 'user') throw new Error('user permission denied') + if (!userData) throw new Error("User does not exist"); + if (userData.role === "user") throw new Error("user permission denied"); if (!bcrypt.compareSync(password, userData.password)) { - throw new Error('Incorrect password') + throw new Error("Incorrect password"); } const payload = { id: userData.id, account: userData.account, - role: userData.role - } + role: userData.role, + }; const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: '30d' - }) + expiresIn: "30d", + }); return res.status(200).json({ - status: 'success', + status: "success", data: { token, - user: userData - } - }) + user: userData, + }, + }); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = adminController +module.exports = adminController; diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 053da4ebce..acea7e9015 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,33 +1,33 @@ -const bcrypt = require('bcryptjs') -const jwt = require('jsonwebtoken') -const sequelize = require('sequelize') -const { imgurFileHandler } = require('../../helpers/file-helpers') +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken"); +const sequelize = require("sequelize"); +const { imgurFileHandler } = require("../../helpers/file-helpers"); -const db = require('../../models') -const helpers = require('../../_helpers') +const db = require("../../models"); +const helpers = require("../../_helpers"); -const { User, Tweet, Reply, Followship, Like } = db -const { Op } = require('sequelize') +const { User, Tweet, Reply, Followship, Like } = db; +const { Op } = require("sequelize"); const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body + const { account, name, email, password, checkPassword } = req.body; if (!account || !name || !email || !password || !checkPassword) { - throw new Error('all the blanks are required') + throw new Error("all the blanks are required"); } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }] - } - }) + [Op.or]: [{ email }, { account }], + }, + }); if (user) { - if (user.account === account) throw new Error('account 已重複註冊!') - if (user.email === email) throw new Error('email 已重複註冊!') + if (user.account === account) throw new Error("account 已重複註冊!"); + if (user.email === email) throw new Error("email 已重複註冊!"); } const createdUser = await User.create({ @@ -35,103 +35,103 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: 'https://picsum.photos/100/100', - cover: 'https://picsum.photos/id/237/700/400', - role: 'user', + avatar: "https://picsum.photos/100/100", + cover: "https://picsum.photos/id/237/700/400", + role: "user", createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create user.', - data: createdUser - }) + status: "success", + message: "Successfully create user.", + data: createdUser, + }); } catch (err) { - next(err) + next(err); } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body + const { account, password } = req.body; if (!account || !password) { - throw new Error('Please enter account and password') + throw new Error("Please enter account and password"); } - const user = await User.findOne({ where: { account } }) - if (!user) throw new Error('User does not exist') - if (user.role === 'admin') throw new Error('admin permission denied') + const user = await User.findOne({ where: { account } }); + if (!user) throw new Error("User does not exist"); + if (user.role === "admin") throw new Error("admin permission denied"); if (!bcrypt.compareSync(password, user.password)) { - throw new Error('Incorrect password') + throw new Error("Incorrect password"); } const payload = { id: user.id, account: user.account, - role: user.role - } + role: user.role, + }; const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: '30d' - }) - const userData = user.toJSON() + expiresIn: "30d", + }); + const userId = user.toJSON().id; res.status(200).json({ - status: 'success', + status: "success", data: { token, - user: userData - } - }) + userId, + }, + }); } catch (err) { - next(err) + next(err); } }, getUser: async (req, res, next) => { try { - const { id } = req.params - const currentUserId = helpers.getUser(req).id + const { id } = req.params; + const currentUserId = helpers.getUser(req).id; const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id } + where: { UserId: id }, }), Followship.count({ - where: { followerId: id } + where: { followerId: id }, }), Followship.count({ - where: { followingId: id } - }) - ]) + where: { followingId: id }, + }), + ]); if (!user) { return res .status(401) - .json({ status: 'error', message: 'This user does not exist' }) + .json({ status: "error", message: "This user does not exist" }); } - delete user.password - user.tweetCount = tweetCount - user.followerCount = followerCount - user.followingCount = followingCount + delete user.password; + user.tweetCount = tweetCount; + user.followerCount = followerCount; + user.followingCount = followingCount; if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); user.isFollowed = checkUserFollowing.some( - follow => follow.followingId === Number(id) - ) + (follow) => follow.followingId === Number(id) + ); } - res.status(200).json(user) + res.status(200).json(user); } catch (err) { - next(err) + next(err); } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id + const userId = req.params.id; const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -140,23 +140,23 @@ const userController = { include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ - { model: User, as: 'author', attributes: ['account', 'name'] } - ] - } + { model: User, as: "author", attributes: ["account", "name"] }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true - }) - ]) + order: [["createdAt", "DESC"]], + nest: true, + }), + ]); - const userRepliesResult = replies.map(reply => ({ + const userRepliesResult = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -166,66 +166,74 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - res.status(200).json(userRepliesResult) + res.status(200).json(userRepliesResult); } catch (err) { - next(err) + next(err); } }, updateUser: async (req, res, next) => { try { - const { id } = req.params - const { account, name, email, password, introduction } = req.body + const { id } = req.params; + const { account, name, email, password, introduction } = req.body; - const user = await User.findByPk(id) + const user = await User.findByPk(id); if (!user) { return res.status(401).json({ - status: 'error', - message: 'This user does not exist' - }) + status: "error", + message: "This user does not exist", + }); } - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; if (!currentUserId) { - throw new Error('Current user ID is missing') + throw new Error("Current user ID is missing"); } if (currentUserId !== Number(id)) { - throw new Error('Cannot edit other users profile') + throw new Error("Cannot edit other users profile"); } - if (name && name.length > 50) { throw new Error('the length of name should less than 50 characters') } + if (name && name.length > 50) { + throw new Error("the length of name should less than 50 characters"); + } if (introduction && introduction.length > 160) { throw new Error( - 'the length of introduction should less than 160 characters' - ) + "the length of introduction should less than 160 characters" + ); } if (account) { - const userByAccount = await User.findOne({ where: { account }, raw: true, nest: true }) - - if (userByAccount && userByAccount.account === account) throw new Error('account 已重複註冊!') + const userByAccount = await User.findOne({ + where: { account }, + raw: true, + nest: true, + }); + + if (userByAccount && userByAccount.account === account) + throw new Error("account 已重複註冊!"); } if (email) { - const userByEmail = await User.findOne({ where: { email } }) - if (userByEmail && userByEmail.email === email) throw new Error('email 已重複註冊!') + const userByEmail = await User.findOne({ where: { email } }); + if (userByEmail && userByEmail.email === email) + throw new Error("email 已重複註冊!"); } - const { files } = req + const { files } = req; - let newAvatar = '' - let newCover = '' + let newAvatar = ""; + let newCover = ""; - if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { - newAvatar = await imgurFileHandler(files.avatar[0]) + if (files && files.avatar && files.avatar[0].fieldname === "avatar") { + newAvatar = await imgurFileHandler(files.avatar[0]); } - if (files && files.cover && files.cover[0].fieldname === 'cover') { - newCover = await imgurFileHandler(files.cover[0]) + if (files && files.cover && files.cover[0].fieldname === "cover") { + newCover = await imgurFileHandler(files.cover[0]); } await user.update({ @@ -235,45 +243,47 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover - }) + cover: newCover || user.cover, + }); res.status(200).json({ - status: 'success', - message: 'Successfully update user.', - data: user - }) + status: "success", + message: "Successfully update user.", + data: user, + }); } catch (err) { - next(err) + next(err); } }, getUserLikes: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); const likeTweets = await Like.findAll({ where: { userId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: Tweet, - as: 'likedTweet', - attributes: { exclude: ['password'] }, + as: "likedTweet", + attributes: { exclude: ["password"] }, include: [ { model: User, - as: 'author', - attributes: ['account', 'name', 'avatar'] - } - ] - } - ] - }) + as: "author", + attributes: ["account", "name", "avatar"], + }, + ], + }, + ], + }); - if (likeTweets.length === 0) { throw new Error('the user did not like any tweet') } + if (likeTweets.length === 0) { + throw new Error("the user did not like any tweet"); + } - const likeTweetsData = likeTweets.map(like => ({ + const likeTweetsData = likeTweets.map((like) => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, @@ -281,33 +291,33 @@ const userController = { tweetLikeCount: like.likedTweet.likeCount, tweetReplyCount: like.likedTweet.replyCount, tweetContent: like.likedTweet.description, - createdAt: like.createdAt - })) + createdAt: like.createdAt, + })); - res.status(200).json(likeTweetsData) + res.status(200).json(likeTweetsData); } catch (err) { - next(err) + next(err); } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); const userTweets = await Tweet.findAll({ where: { userId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: User, - as: 'author', - attributes: { exclude: ['password'] } - } - ] - }) + as: "author", + attributes: { exclude: ["password"] }, + }, + ], + }); - const userTweetsData = userTweets.map(tweet => ({ + const userTweetsData = userTweets.map((tweet) => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -315,103 +325,103 @@ const userController = { tweetLikeCount: tweet.likeCount, tweetReplyCount: tweet.replyCount, description: tweet.description, - createdAt: tweet.createdAt - })) + createdAt: tweet.createdAt, + })); - res.status(200).json(userTweetsData) + res.status(200).json(userTweetsData); } catch (err) { - next(err) + next(err); } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; const followers = await Followship.findAll({ where: { followingId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: User, - as: 'follower', - attributes: { exclude: ['password'] } - } + as: "follower", + attributes: { exclude: ["password"] }, + }, ], attributes: [ - 'followerId', - 'followingId', - 'createdAt', - 'updatedAt', + "followerId", + "followingId", + "createdAt", + "updatedAt", [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - 'isFollowed' - ] + "isFollowed", + ], ], raw: true, - nest: true - }) + nest: true, + }); - const userFollowersData = followers.map(follower => { + const userFollowersData = followers.map((follower) => { return { - ...follower - } - }) + ...follower, + }; + }); - res.status(200).json(userFollowersData) + res.status(200).json(userFollowersData); } catch (err) { - next(err) + next(err); } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') - const currentUserId = helpers.getUser(req).id + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); + const currentUserId = helpers.getUser(req).id; const following = await Followship.findAll({ where: { followerId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: User, - as: 'following', - attributes: { exclude: ['password'] } - } + as: "following", + attributes: { exclude: ["password"] }, + }, ], attributes: [ - 'followerId', - 'followingId', - 'createdAt', - 'updatedAt', + "followerId", + "followingId", + "createdAt", + "updatedAt", [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - 'isFollowed' - ] + "isFollowed", + ], ], raw: true, - nest: true - }) + nest: true, + }); - const userFollowersData = following.map(follower => { + const userFollowersData = following.map((follower) => { return { - ...follower - } - }) + ...follower, + }; + }); - res.status(200).json(userFollowersData) + res.status(200).json(userFollowersData); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = userController +module.exports = userController; From cec76d648282ecaa24f276276bf33556eb2f3ba7 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 15:21:46 +0800 Subject: [PATCH 088/170] feat: modify seeder amount --- controllers/apis/admin-controller.js | 118 +++--- controllers/apis/user-controller.js | 390 ++++++++++---------- seeders/20230821044414-users-seed-file.js | 2 +- seeders/20230821074916-tweets-seed-file.js | 5 +- seeders/20230821081029-replies-seed-file.js | 2 +- 5 files changed, 264 insertions(+), 253 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 2665363243..0d2f850c81 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -1,7 +1,7 @@ -const bcrypt = require("bcryptjs"); -const db = require("../../models"); -const { User, Tweet, Like } = db; -const jwt = require("jsonwebtoken"); +const bcrypt = require('bcryptjs') +const db = require('../../models') +const { User, Tweet, Like } = db +const jwt = require('jsonwebtoken') const adminController = { getUsers: async (req, res, next) => { @@ -9,21 +9,21 @@ const adminController = { const options = { raw: true, attributes: { - exclude: ["email", "password", "updatedAt", "createdAt"], - }, - }; - const users = await User.findAll(options); + exclude: ['email', 'password', 'updatedAt', 'createdAt'] + } + } + const users = await User.findAll(options) // console.log("usersbeforeforeach", users); - users.forEach((user) => { + users.forEach(user => { if (user.introduction) { - user.introduction = user.introduction.substring(0, 50); + user.introduction = user.introduction.substring(0, 50) } - }); + }) // console.log(users); - res.status(200).json(users); + res.status(200).json(users) } catch (error) { - next(error); + next(error) } }, getTweets: async (req, res, next) => { @@ -32,27 +32,27 @@ const adminController = { raw: true, nest: true, attributes: [ - "id", - "description", - "replyCount", - "likeCount", - "createdAt", + 'id', + 'description', + 'replyCount', + 'likeCount', + 'createdAt' ], include: [ { model: User, - attributes: ["id", "account", "name", "avatar"], - as: "author", - }, - ], - }; - const tweets = await Tweet.findAll(options); - tweets.forEach((tweet) => { - tweet.description = tweet.description.substring(0, 50); - }); - res.status(200).json(tweets); + attributes: ['id', 'account', 'name', 'avatar'], + as: 'author' + } + ] + } + const tweets = await Tweet.findAll(options) + tweets.forEach(tweet => { + tweet.description = tweet.description.substring(0, 50) + }) + res.status(200).json(tweets) } catch (err) { - next(err); + next(err) } }, @@ -62,67 +62,67 @@ const adminController = { Tweet.destroy({ where: { id: req.params.id }, raw: true, - nest: true, + nest: true }), Like.destroy({ where: { TweetId: req.params.id }, raw: true, - nest: true, - }), - ]); + nest: true + }) + ]) if (!tweet) { throw new Error( - "此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除" - ); + '此貼文不存在,可能是 Parameters 的資料錯誤或已經被刪除' + ) } return res.status(200).json({ - status: "success", - message: "Successfully delete tweet.", - }); + status: 'success', + message: 'Successfully delete tweet.' + }) } catch (error) { return res.status(500).json({ - status: "error", - message: error.message, - }); + status: 'error', + message: error.message + }) } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body; + const { account, password } = req.body if (!account || !password) { - throw new Error("Please enter account and password"); + throw new Error('Please enter account and password') } - const userData = await User.findOne({ where: { account } }); + const userData = await User.findOne({ where: { account } }) - if (!userData) throw new Error("User does not exist"); - if (userData.role === "user") throw new Error("user permission denied"); + if (!userData) throw new Error('User does not exist') + if (userData.role === 'user') throw new Error('user permission denied') if (!bcrypt.compareSync(password, userData.password)) { - throw new Error("Incorrect password"); + throw new Error('Incorrect password') } const payload = { id: userData.id, account: userData.account, - role: userData.role, - }; + role: userData.role + } const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "30d", - }); + expiresIn: '30d' + }) return res.status(200).json({ - status: "success", + status: 'success', data: { token, - user: userData, - }, - }); + user: userData + } + }) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = adminController; +module.exports = adminController diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index acea7e9015..0a2233dfdf 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,33 +1,33 @@ -const bcrypt = require("bcryptjs"); -const jwt = require("jsonwebtoken"); -const sequelize = require("sequelize"); -const { imgurFileHandler } = require("../../helpers/file-helpers"); +const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') +const sequelize = require('sequelize') +const { imgurFileHandler } = require('../../helpers/file-helpers') -const db = require("../../models"); -const helpers = require("../../_helpers"); +const db = require('../../models') +const helpers = require('../../_helpers') -const { User, Tweet, Reply, Followship, Like } = db; -const { Op } = require("sequelize"); +const { User, Tweet, Reply, Followship, Like } = db +const { Op } = require('sequelize') const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body; + const { account, name, email, password, checkPassword } = req.body if (!account || !name || !email || !password || !checkPassword) { - throw new Error("all the blanks are required"); + throw new Error('all the blanks are required') } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }], - }, - }); + [Op.or]: [{ email }, { account }] + } + }) if (user) { - if (user.account === account) throw new Error("account 已重複註冊!"); - if (user.email === email) throw new Error("email 已重複註冊!"); + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') } const createdUser = await User.create({ @@ -35,103 +35,103 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: "https://picsum.photos/100/100", - cover: "https://picsum.photos/id/237/700/400", - role: "user", + avatar: 'https://picsum.photos/100/100', + cover: 'https://picsum.photos/id/237/700/400', + role: 'user', createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create user.", - data: createdUser, - }); + status: 'success', + message: 'Successfully create user.', + data: createdUser + }) } catch (err) { - next(err); + next(err) } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body; + const { account, password } = req.body if (!account || !password) { - throw new Error("Please enter account and password"); + throw new Error('Please enter account and password') } - const user = await User.findOne({ where: { account } }); - if (!user) throw new Error("User does not exist"); - if (user.role === "admin") throw new Error("admin permission denied"); + const user = await User.findOne({ where: { account } }) + if (!user) throw new Error('User does not exist') + if (user.role === 'admin') throw new Error('admin permission denied') if (!bcrypt.compareSync(password, user.password)) { - throw new Error("Incorrect password"); + throw new Error('Incorrect password') } const payload = { id: user.id, account: user.account, - role: user.role, - }; + role: user.role + } const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "30d", - }); - const userId = user.toJSON().id; + expiresIn: '30d' + }) + const userId = user.toJSON().id res.status(200).json({ - status: "success", + status: 'success', data: { token, - userId, - }, - }); + userId + } + }) } catch (err) { - next(err); + next(err) } }, getUser: async (req, res, next) => { try { - const { id } = req.params; - const currentUserId = helpers.getUser(req).id; + const { id } = req.params + const currentUserId = helpers.getUser(req).id const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id }, + where: { UserId: id } }), Followship.count({ - where: { followerId: id }, + where: { followerId: id } }), Followship.count({ - where: { followingId: id }, - }), - ]); + where: { followingId: id } + }) + ]) if (!user) { return res .status(401) - .json({ status: "error", message: "This user does not exist" }); + .json({ status: 'error', message: 'This user does not exist' }) } - delete user.password; - user.tweetCount = tweetCount; - user.followerCount = followerCount; - user.followingCount = followingCount; + delete user.password + user.tweetCount = tweetCount + user.followerCount = followerCount + user.followingCount = followingCount if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) user.isFollowed = checkUserFollowing.some( - (follow) => follow.followingId === Number(id) - ); + follow => follow.followingId === Number(id) + ) } - res.status(200).json(user); + res.status(200).json(user) } catch (err) { - next(err); + next(err) } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id; + const userId = req.params.id const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -140,23 +140,23 @@ const userController = { include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ - { model: User, as: "author", attributes: ["account", "name"] }, - ], - }, + { model: User, as: 'author', attributes: ['account', 'name'] } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, - }), - ]); + order: [['createdAt', 'DESC']], + nest: true + }) + ]) - const userRepliesResult = replies.map((reply) => ({ + const userRepliesResult = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -166,74 +166,76 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(userRepliesResult); + res.status(200).json(userRepliesResult) } catch (err) { - next(err); + next(err) } }, updateUser: async (req, res, next) => { try { - const { id } = req.params; - const { account, name, email, password, introduction } = req.body; + const { id } = req.params + const { account, name, email, password, introduction } = req.body - const user = await User.findByPk(id); + const user = await User.findByPk(id) if (!user) { return res.status(401).json({ - status: "error", - message: "This user does not exist", - }); + status: 'error', + message: 'This user does not exist' + }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id if (!currentUserId) { - throw new Error("Current user ID is missing"); + throw new Error('Current user ID is missing') } if (currentUserId !== Number(id)) { - throw new Error("Cannot edit other users profile"); + throw new Error('Cannot edit other users profile') } if (name && name.length > 50) { - throw new Error("the length of name should less than 50 characters"); + throw new Error('the length of name should less than 50 characters') } if (introduction && introduction.length > 160) { throw new Error( - "the length of introduction should less than 160 characters" - ); + 'the length of introduction should less than 160 characters' + ) } if (account) { const userByAccount = await User.findOne({ where: { account }, raw: true, - nest: true, - }); + nest: true + }) - if (userByAccount && userByAccount.account === account) - throw new Error("account 已重複註冊!"); + if (userByAccount && userByAccount.account === account) { + throw new Error('account 已重複註冊!') + } } if (email) { - const userByEmail = await User.findOne({ where: { email } }); - if (userByEmail && userByEmail.email === email) - throw new Error("email 已重複註冊!"); + const userByEmail = await User.findOne({ where: { email } }) + if (userByEmail && userByEmail.email === email) { + throw new Error('email 已重複註冊!') + } } - const { files } = req; + const { files } = req - let newAvatar = ""; - let newCover = ""; + let newAvatar = '' + let newCover = '' - if (files && files.avatar && files.avatar[0].fieldname === "avatar") { - newAvatar = await imgurFileHandler(files.avatar[0]); + if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { + newAvatar = await imgurFileHandler(files.avatar[0]) } - if (files && files.cover && files.cover[0].fieldname === "cover") { - newCover = await imgurFileHandler(files.cover[0]); + if (files && files.cover && files.cover[0].fieldname === 'cover') { + newCover = await imgurFileHandler(files.cover[0]) } await user.update({ @@ -243,47 +245,47 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover, - }); + cover: newCover || user.cover + }) res.status(200).json({ - status: "success", - message: "Successfully update user.", - data: user, - }); + status: 'success', + message: 'Successfully update user.', + data: user + }) } catch (err) { - next(err); + next(err) } }, getUserLikes: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const likeTweets = await Like.findAll({ where: { userId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: Tweet, - as: "likedTweet", - attributes: { exclude: ["password"] }, + as: 'likedTweet', + attributes: { exclude: ['password'] }, include: [ { model: User, - as: "author", - attributes: ["account", "name", "avatar"], - }, - ], - }, - ], - }); + as: 'author', + attributes: ['account', 'name', 'avatar'] + } + ] + } + ] + }) if (likeTweets.length === 0) { - throw new Error("the user did not like any tweet"); + throw new Error('the user did not like any tweet') } - const likeTweetsData = likeTweets.map((like) => ({ + const likeTweetsData = likeTweets.map(like => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, @@ -291,33 +293,43 @@ const userController = { tweetLikeCount: like.likedTweet.likeCount, tweetReplyCount: like.likedTweet.replyCount, tweetContent: like.likedTweet.description, - createdAt: like.createdAt, - })); + createdAt: like.createdAt + })) - res.status(200).json(likeTweetsData); + res.status(200).json(likeTweetsData) } catch (err) { - next(err); + next(err) } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const userTweets = await Tweet.findAll({ where: { userId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], + // attributes:['id','description', [ + // sequelize.literal( + // '(SELECT COUNT(DISTINCT id) FROM Like WHERE user_id = User.id)' + // ), + // 'totalFollowers' + // ],] include: [ { model: User, - as: "author", - attributes: { exclude: ["password"] }, - }, - ], - }); - - const userTweetsData = userTweets.map((tweet) => ({ + as: 'author', + attributes: { exclude: ['password'] } + } + // { + // model:Like, + // as + // } + ] + }) + + const userTweetsData = userTweets.map(tweet => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -325,103 +337,103 @@ const userController = { tweetLikeCount: tweet.likeCount, tweetReplyCount: tweet.replyCount, description: tweet.description, - createdAt: tweet.createdAt, - })); + createdAt: tweet.createdAt + })) - res.status(200).json(userTweetsData); + res.status(200).json(userTweetsData) } catch (err) { - next(err); + next(err) } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id const followers = await Followship.findAll({ where: { followingId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: User, - as: "follower", - attributes: { exclude: ["password"] }, - }, + as: 'follower', + attributes: { exclude: ['password'] } + } ], attributes: [ - "followerId", - "followingId", - "createdAt", - "updatedAt", + 'followerId', + 'followingId', + 'createdAt', + 'updatedAt', [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - "isFollowed", - ], + 'isFollowed' + ] ], raw: true, - nest: true, - }); + nest: true + }) - const userFollowersData = followers.map((follower) => { + const userFollowersData = followers.map(follower => { return { - ...follower, - }; - }); + ...follower + } + }) - res.status(200).json(userFollowersData); + res.status(200).json(userFollowersData) } catch (err) { - next(err); + next(err) } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); - const currentUserId = helpers.getUser(req).id; + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') + const currentUserId = helpers.getUser(req).id const following = await Followship.findAll({ where: { followerId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: User, - as: "following", - attributes: { exclude: ["password"] }, - }, + as: 'following', + attributes: { exclude: ['password'] } + } ], attributes: [ - "followerId", - "followingId", - "createdAt", - "updatedAt", + 'followerId', + 'followingId', + 'createdAt', + 'updatedAt', [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - "isFollowed", - ], + 'isFollowed' + ] ], raw: true, - nest: true, - }); + nest: true + }) - const userFollowersData = following.map((follower) => { + const userFollowersData = following.map(follower => { return { - ...follower, - }; - }); + ...follower + } + }) - res.status(200).json(userFollowersData); + res.status(200).json(userFollowersData) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = userController; +module.exports = userController diff --git a/seeders/20230821044414-users-seed-file.js b/seeders/20230821044414-users-seed-file.js index b27e3c252a..84f60a1ce9 100644 --- a/seeders/20230821044414-users-seed-file.js +++ b/seeders/20230821044414-users-seed-file.js @@ -25,7 +25,7 @@ module.exports = { } data.push(admin) - for (let i = 1; i <= 50; i++) { + for (let i = 1; i <= 20; i++) { const user = { id: i + 1, email: `user${i}@example.com`, diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index 8c3979ccc3..f0390b6fdb 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -11,9 +11,8 @@ module.exports = { nest: true, attributes: ['id'] }) - // eslint-disable-next-line array-callback-return - Array.from({ length: 10 }).map((user, i) => { - for (let j = 0; j < 10; ++j) { + Array.from({ length: 10 }).map((el, i) => { + for (let j = 0; j < 5; ++j) { data.push({ description: faker.lorem.text(140), created_at: new Date(), diff --git a/seeders/20230821081029-replies-seed-file.js b/seeders/20230821081029-replies-seed-file.js index f72ce53031..93ba3e42ee 100644 --- a/seeders/20230821081029-replies-seed-file.js +++ b/seeders/20230821081029-replies-seed-file.js @@ -18,7 +18,7 @@ module.exports = { await queryInterface.bulkInsert( 'Replies', - Array.from({ length: 150 }).map((d, i) => { + Array.from({ length: 50 }).map((d, i) => { const tweet = { Tweet_id: tweetData[Math.floor(i / 3)].id, User_id: userData[Math.floor(Math.random() * userData.length)].id, From 4077a5153b4d4603b63b1738d8d4d0610b7583fe Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 15:39:54 +0800 Subject: [PATCH 089/170] fix: admin controller get tweets --- controllers/apis/admin-controller.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 0d2f850c81..04d10927b1 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -31,13 +31,7 @@ const adminController = { const options = { raw: true, nest: true, - attributes: [ - 'id', - 'description', - 'replyCount', - 'likeCount', - 'createdAt' - ], + attributes: ['id', 'description', 'createdAt'], include: [ { model: User, From cdb738f609fe6378c64ed91700844bb54b8b6e41 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 16:31:44 +0800 Subject: [PATCH 090/170] feat: modify admin/users response data --- controllers/apis/admin-controller.js | 36 +++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 04d10927b1..2713473b07 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -2,15 +2,45 @@ const bcrypt = require('bcryptjs') const db = require('../../models') const { User, Tweet, Like } = db const jwt = require('jsonwebtoken') +const sequelize = require('sequelize') const adminController = { getUsers: async (req, res, next) => { try { const options = { raw: true, - attributes: { - exclude: ['email', 'password', 'updatedAt', 'createdAt'] - } + attributes: [ + 'id', + 'name', + 'account', + 'introduction', + 'avatar', + 'cover', + [ + sequelize.literal( + '(SELECT COUNT(DISTINCT id) FROM Tweets WHERE Tweets.user_id = User.id)' + ), + 'tweetCount' + ], + [ + sequelize.literal( + '(SELECT COUNT(DISTINCT id) FROM Followships WHERE Followships.following_id = User.id)' + ), + 'followerCount' + ], + [ + sequelize.literal( + '(SELECT COUNT(DISTINCT id) FROM Followships WHERE Followships.follower_id = User.id)' + ), + 'followingCount' + ], + [ + sequelize.literal( + '(SELECT COUNT(DISTINCT id) FROM Likes WHERE Likes.user_id = User.id)' + ), + 'likeCount' + ] + ] } const users = await User.findAll(options) // console.log("usersbeforeforeach", users); From fa147c60b4c33e717ccb69b5d40db002b8ad37dd Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 17:05:16 +0800 Subject: [PATCH 091/170] fix: modify getUser order by createdat --- controllers/apis/admin-controller.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 2713473b07..8e1eccaaeb 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -40,7 +40,8 @@ const adminController = { ), 'likeCount' ] - ] + ], + order: [[sequelize.col('tweetCount'), 'DESC'], ['createdAt']] } const users = await User.findAll(options) // console.log("usersbeforeforeach", users); From 695a1b539366725d42c78642543a646d8b2e7405 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 17:19:26 +0800 Subject: [PATCH 092/170] fix: add createdAt to getTweets reponse --- controllers/apis/tweet-controller.js | 259 ++++++++++++++------------- 1 file changed, 136 insertions(+), 123 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index c9053a94ed..4048048610 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,38 +1,50 @@ -const { Tweet, Like, Reply, User } = require('../../models') -const helpers = require('../../_helpers') +const { Tweet, Like, Reply, User } = require("../../models"); +const helpers = require("../../_helpers"); // const defaultLimit = 10 +const sequelize = require("sequelize"); const tweetContorller = { getTweets: async (req, res, next) => { try { - const getUser = helpers.getUser(req) - const userId = getUser.id + const getUser = helpers.getUser(req); + const userId = getUser.id; const options = { attributes: [ - 'id', - 'description', - 'likeCount', - 'replyCount', - 'createdAt' + "id", + "description", + "likeCount", + "replyCount", + "createdAt", + // [ + // sequelize.literal( + // '(SELECT COUNT(DISTINCT id) FROM Likes WHERE Likes.tweet_id = Tweet.id)' + // ), + // 'likeCount' + // ][ + // (sequelize.literal( + // '(SELECT COUNT(DISTINCT id) FROM Replies WHERE Replies.tweet_id = Tweet.id)' + // ), + // 'replyCount') + // ] ], - order: [['createdAt', 'desc']], + order: [["createdAt", "desc"]], subQuery: false, include: [ { model: User, - attributes: ['id', 'account', 'name', 'avatar'], - as: 'author', - where: { role: 'user' } + attributes: ["id", "account", "name", "avatar"], + as: "author", + where: { role: "user" }, }, { model: Like, - attributes: ['userId'] - } - ] - } - const tweets = await Tweet.findAll(options) - console.log(tweets) - const dataTweets = tweets.map(tweet => ({ + attributes: ["userId"], + }, + ], + }; + const tweets = await Tweet.findAll(options); + console.log(tweets); + const dataTweets = tweets.map((tweet) => ({ id: tweet.id, authorId: tweet.author.id, authorAccount: tweet.author.account, @@ -41,138 +53,139 @@ const tweetContorller = { description: tweet.description.substring(0, 140), likeCount: tweet.likeCount, replyCount: tweet.replyCount, - isLiked: tweet.Likes.some(i => i.userId === userId) - })) - res.status(200).json(dataTweets) + isLiked: tweet.Likes.some((i) => i.userId === userId), + createdAt: tweet.createdAt, + })); + res.status(200).json(dataTweets); } catch (err) { - next(err) + next(err); } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const tweet = await Tweet.findByPk(tweetId) + const tweetId = req.params.tweet_id; + const tweet = await Tweet.findByPk(tweetId); - if (!tweet) throw new Error("Tweet didn't exist!") + if (!tweet) throw new Error("Tweet didn't exist!"); - res.status(200).json(tweet) + res.status(200).json(tweet); } catch (err) { - next(err) + next(err); } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (like) throw new Error('You have liked this tweet!') + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (like) throw new Error("You have liked this tweet!"); const createdLike = await Like.create({ userId, - tweetId - }) + tweetId, + }); res.status(200).json({ - status: 'success', + status: "success", data: createdLike, - isLiked: true - }) + isLiked: true, + }); } catch (err) { - next(err) + next(err); } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (!like) throw new Error("You haven't liked this tweet!") + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!like) throw new Error("You haven't liked this tweet!"); await Like.destroy({ where: { userId, - tweetId - } - }) + tweetId, + }, + }); res.status(200).json({ - status: 'success', - isLiked: false - }) + status: "success", + isLiked: false, + }); } catch (err) { - next(err) + next(err); } }, createTweet: async (req, res, next) => { try { - const { description } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id - if (!description) throw new Error('文章內容不可為空白') - if (description.length > 140) throw new Error('文章內容不可超過 140 字') + const { description } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; + if (!description) throw new Error("文章內容不可為空白"); + if (description.length > 140) throw new Error("文章內容不可超過 140 字"); const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create tweet.', - data: createdTweet - }) + status: "success", + message: "Successfully create tweet.", + data: createdTweet, + }); } catch (err) { - next(err) + next(err); } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ { model: User, - as: 'author', - attributes: ['account', 'name', 'avatar'] - } - ] - } + as: "author", + attributes: ["account", "name", "avatar"], + }, + ], + }, ], - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], nest: true, - raw: true - }) + raw: true, + }); - if (!replies) throw new Error('This tweet has no replies') - console.log(replies) - const repliesData = replies.map(reply => ({ + if (!replies) throw new Error("This tweet has no replies"); + console.log(replies); + const repliesData = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -182,78 +195,78 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - res.status(200).json(repliesData) + res.status(200).json(repliesData); } catch (err) { - next(err) + next(err); } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const { comment } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const { comment } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; - if (!comment) throw new Error('回覆內容不可為空白') + if (!comment) throw new Error("回覆內容不可為空白"); const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'successfully created reply', - replyData - }) + status: "success", + message: "successfully created reply", + replyData, + }); } catch (err) { - next(err) + next(err); } }, getLikes: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId + tweetId, }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ['password', 'introduction', 'cover'] } - } - ] - }) - ]) + attributes: { exclude: ["password", "introduction", "cover"] }, + }, + ], + }), + ]); - if (!tweet) throw new Error("Tweet didn't exist!") - if (!likes) throw new Error('NO ONE liked this tweet!') - const likedData = likes.map(like => ({ + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!likes) throw new Error("NO ONE liked this tweet!"); + const likedData = likes.map((like) => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar - })) + likedUserAvatar: like.User.avatar, + })); res.status(200).json({ - status: 'success', - message: 'successfully get all the liked users', - likedData - }) + status: "success", + message: "successfully get all the liked users", + likedData, + }); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = tweetContorller +module.exports = tweetContorller; From 21ae3c146ed6c548b961368d85b786e59f785624 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Mon, 28 Aug 2023 20:02:58 +0800 Subject: [PATCH 093/170] feat: merge remote --- controllers/apis/tweet-controller.js | 5 ++-- seeders/20230824144658-likes-seed-file.js.js | 28 ++++++++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 2630c29e1a..3bfd123693 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -133,9 +133,10 @@ const tweetContorller = { } ], order: [['createdAt', 'DESC']], - nest: true + nest: true, + raw: true }) - + console.log(replies) if (!replies) throw new Error('This tweet has no replies') console.log(replies) const repliesData = replies.map(reply => ({ diff --git a/seeders/20230824144658-likes-seed-file.js.js b/seeders/20230824144658-likes-seed-file.js.js index 196a4633e9..f8fe14338d 100644 --- a/seeders/20230824144658-likes-seed-file.js.js +++ b/seeders/20230824144658-likes-seed-file.js.js @@ -1,33 +1,33 @@ -"use strict"; +'use strict' module.exports = { up: async (queryInterface, Sequelize) => { const users = await queryInterface.sequelize.query( - "SELECT id FROM Users ;", + 'SELECT id FROM Users;', { type: queryInterface.sequelize.QueryTypes.SELECT } - ); + ) const tweets = await queryInterface.sequelize.query( - "SELECT id FROM Tweets;", + 'SELECT id FROM Tweets;', { type: queryInterface.sequelize.QueryTypes.SELECT } - ); + ) - const likes = []; + const likes = [] - tweets.forEach((tweet) => { + tweets.forEach(tweet => { likes.push( ...Array.from({ length: 2 }, () => ({ User_id: users[Math.floor(Math.random() * users.length)].id, Tweet_id: tweet.id, created_at: new Date(), - updated_at: new Date(), + updated_at: new Date() })) - ); - }); - await queryInterface.bulkInsert("Likes", likes); + ) + }) + await queryInterface.bulkInsert('Likes', likes) }, down: async (queryInterface, Sequelize) => { - return queryInterface.bulkDelete("Likes", null, {}); - }, -}; + return queryInterface.bulkDelete('Likes', null, {}) + } +} From f2fb1da76077659ec77aaf5efa5322bc40c12198 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 22:26:00 +0800 Subject: [PATCH 094/170] fix : modify getTweet:id --- controllers/apis/tweet-controller.js | 278 +++++++++++++++------------ 1 file changed, 153 insertions(+), 125 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 4048048610..a0678d28d3 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,20 +1,20 @@ -const { Tweet, Like, Reply, User } = require("../../models"); -const helpers = require("../../_helpers"); +const { Tweet, Like, Reply, User } = require('../../models') +const helpers = require('../../_helpers') // const defaultLimit = 10 -const sequelize = require("sequelize"); +const sequelize = require('sequelize') const tweetContorller = { getTweets: async (req, res, next) => { try { - const getUser = helpers.getUser(req); - const userId = getUser.id; + const getUser = helpers.getUser(req) + const userId = getUser.id const options = { attributes: [ - "id", - "description", - "likeCount", - "replyCount", - "createdAt", + 'id', + 'description', + 'likeCount', + 'replyCount', + 'createdAt' // [ // sequelize.literal( // '(SELECT COUNT(DISTINCT id) FROM Likes WHERE Likes.tweet_id = Tweet.id)' @@ -27,24 +27,25 @@ const tweetContorller = { // 'replyCount') // ] ], - order: [["createdAt", "desc"]], + order: [['createdAt', 'desc']], subQuery: false, include: [ { model: User, - attributes: ["id", "account", "name", "avatar"], - as: "author", - where: { role: "user" }, + attributes: ['id', 'account', 'name', 'avatar'], + as: 'author', + where: { role: 'user' } }, { model: Like, - attributes: ["userId"], - }, - ], - }; - const tweets = await Tweet.findAll(options); - console.log(tweets); - const dataTweets = tweets.map((tweet) => ({ + attributes: ['userId'] + } + ] + } + const tweets = await Tweet.findAll(options) + console.log(tweets) + + const dataTweets = tweets.map(tweet => ({ id: tweet.id, authorId: tweet.author.id, authorAccount: tweet.author.account, @@ -53,139 +54,166 @@ const tweetContorller = { description: tweet.description.substring(0, 140), likeCount: tweet.likeCount, replyCount: tweet.replyCount, - isLiked: tweet.Likes.some((i) => i.userId === userId), - createdAt: tweet.createdAt, - })); - res.status(200).json(dataTweets); + isLiked: tweet.Likes.some(i => i.userId === userId), + createdAt: tweet.createdAt + })) + res.status(200).json(dataTweets) } catch (err) { - next(err); + next(err) } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const tweet = await Tweet.findByPk(tweetId); + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id + const tweet = await Tweet.findOne({ + where: { id: tweetId }, + include: [ + { + model: User, + attributes: ['id', 'account', 'name', 'avatar'], + as: 'author' + }, + { + model: Like, + attributes: ['userId'] + } + ] + }) - if (!tweet) throw new Error("Tweet didn't exist!"); + if (!tweet) throw new Error("Tweet didn't exist!") + console.log(tweet) - res.status(200).json(tweet); + const tweetData = [tweet].map(t => ({ + id: t.id, + authorName: t.author.name, + authorAaccount: t.author.account, + authorAvatar: t.author.avatar, + description: t.description, + likeCount: t.likeCount, + replyCount: t.replyCount, + isLiked: t.Likes.some(i => i.userId === userId), + createdAt: t.createdAt + })) + res.status(200).json(tweetData) } catch (err) { - next(err); + next(err) } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (like) throw new Error("You have liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (like) throw new Error('You have liked this tweet!') const createdLike = await Like.create({ userId, - tweetId, - }); + tweetId + }) res.status(200).json({ - status: "success", + status: 'success', data: createdLike, - isLiked: true, - }); + isLiked: true + }) } catch (err) { - next(err); + next(err) } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!like) throw new Error("You haven't liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (!like) throw new Error("You haven't liked this tweet!") await Like.destroy({ where: { userId, - tweetId, - }, - }); + tweetId + } + }) res.status(200).json({ - status: "success", - isLiked: false, - }); + status: 'success', + isLiked: false + }) } catch (err) { - next(err); + next(err) } }, createTweet: async (req, res, next) => { try { - const { description } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; - if (!description) throw new Error("文章內容不可為空白"); - if (description.length > 140) throw new Error("文章內容不可超過 140 字"); + const { description } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id + if (!description) throw new Error('文章內容不可為空白') + if (description.length > 140) throw new Error('文章內容不可超過 140 字') const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create tweet.", - data: createdTweet, - }); + status: 'success', + message: 'Successfully create tweet.', + data: createdTweet + }) } catch (err) { - next(err); + next(err) } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ { model: User, - as: "author", - attributes: ["account", "name", "avatar"], - }, - ], - }, + as: 'author', + attributes: ['account', 'name', 'avatar'] + } + ] + } ], - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], nest: true, - raw: true, - }); + raw: true + }) - if (!replies) throw new Error("This tweet has no replies"); - console.log(replies); - const repliesData = replies.map((reply) => ({ + if (!replies) throw new Error('This tweet has no replies') + console.log(replies) + const repliesData = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -195,78 +223,78 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(repliesData); + res.status(200).json(repliesData) } catch (err) { - next(err); + next(err) } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const { comment } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const { comment } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id - if (!comment) throw new Error("回覆內容不可為空白"); + if (!comment) throw new Error('回覆內容不可為空白') const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "successfully created reply", - replyData, - }); + status: 'success', + message: 'successfully created reply', + replyData + }) } catch (err) { - next(err); + next(err) } }, getLikes: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId, + tweetId }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ["password", "introduction", "cover"] }, - }, - ], - }), - ]); + attributes: { exclude: ['password', 'introduction', 'cover'] } + } + ] + }) + ]) - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!likes) throw new Error("NO ONE liked this tweet!"); - const likedData = likes.map((like) => ({ + if (!tweet) throw new Error("Tweet didn't exist!") + if (!likes) throw new Error('NO ONE liked this tweet!') + const likedData = likes.map(like => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar, - })); + likedUserAvatar: like.User.avatar + })) res.status(200).json({ - status: "success", - message: "successfully get all the liked users", - likedData, - }); + status: 'success', + message: 'successfully get all the liked users', + likedData + }) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = tweetContorller; +module.exports = tweetContorller From 944216cbd3d76766263dbfbf155d107d33c94b45 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 22:47:20 +0800 Subject: [PATCH 095/170] fix: getTweets like count and reply count --- controllers/apis/tweet-controller.js | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index a0678d28d3..c8095d9523 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,7 +1,5 @@ const { Tweet, Like, Reply, User } = require('../../models') const helpers = require('../../_helpers') -// const defaultLimit = 10 -const sequelize = require('sequelize') const tweetContorller = { getTweets: async (req, res, next) => { @@ -15,17 +13,6 @@ const tweetContorller = { 'likeCount', 'replyCount', 'createdAt' - // [ - // sequelize.literal( - // '(SELECT COUNT(DISTINCT id) FROM Likes WHERE Likes.tweet_id = Tweet.id)' - // ), - // 'likeCount' - // ][ - // (sequelize.literal( - // '(SELECT COUNT(DISTINCT id) FROM Replies WHERE Replies.tweet_id = Tweet.id)' - // ), - // 'replyCount') - // ] ], order: [['createdAt', 'desc']], subQuery: false, @@ -37,8 +24,11 @@ const tweetContorller = { where: { role: 'user' } }, { - model: Like, - attributes: ['userId'] + model: Like + }, + { + model: Reply, + as: 'replies' } ] } @@ -52,8 +42,8 @@ const tweetContorller = { authorName: tweet.author.name, authorAvatar: tweet.author.avatar, description: tweet.description.substring(0, 140), - likeCount: tweet.likeCount, - replyCount: tweet.replyCount, + likeCount: tweet.Likes.length, + replyCount: tweet.replies.length, isLiked: tweet.Likes.some(i => i.userId === userId), createdAt: tweet.createdAt })) From 68091511f0a01adbf19907c0f3fddccdbc37e932 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 22:48:24 +0800 Subject: [PATCH 096/170] fix: typo --- controllers/apis/tweet-controller.js | 276 +++++++++++++-------------- 1 file changed, 138 insertions(+), 138 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index c8095d9523..183862c169 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,41 +1,41 @@ -const { Tweet, Like, Reply, User } = require('../../models') -const helpers = require('../../_helpers') +const { Tweet, Like, Reply, User } = require("../../models"); +const helpers = require("../../_helpers"); const tweetContorller = { getTweets: async (req, res, next) => { try { - const getUser = helpers.getUser(req) - const userId = getUser.id + const getUser = helpers.getUser(req); + const userId = getUser.id; const options = { attributes: [ - 'id', - 'description', - 'likeCount', - 'replyCount', - 'createdAt' + "id", + "description", + "likeCount", + "replyCount", + "createdAt", ], - order: [['createdAt', 'desc']], + order: [["createdAt", "desc"]], subQuery: false, include: [ { model: User, - attributes: ['id', 'account', 'name', 'avatar'], - as: 'author', - where: { role: 'user' } + attributes: ["id", "account", "name", "avatar"], + as: "author", + where: { role: "user" }, }, { - model: Like + model: Like, }, { model: Reply, - as: 'replies' - } - ] - } - const tweets = await Tweet.findAll(options) - console.log(tweets) + as: "replies", + }, + ], + }; + const tweets = await Tweet.findAll(options); + console.log(tweets); - const dataTweets = tweets.map(tweet => ({ + const dataTweets = tweets.map((tweet) => ({ id: tweet.id, authorId: tweet.author.id, authorAccount: tweet.author.account, @@ -44,166 +44,166 @@ const tweetContorller = { description: tweet.description.substring(0, 140), likeCount: tweet.Likes.length, replyCount: tweet.replies.length, - isLiked: tweet.Likes.some(i => i.userId === userId), - createdAt: tweet.createdAt - })) - res.status(200).json(dataTweets) + isLiked: tweet.Likes.some((i) => i.userId === userId), + createdAt: tweet.createdAt, + })); + res.status(200).json(dataTweets); } catch (err) { - next(err) + next(err); } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const tweet = await Tweet.findOne({ where: { id: tweetId }, include: [ { model: User, - attributes: ['id', 'account', 'name', 'avatar'], - as: 'author' + attributes: ["id", "account", "name", "avatar"], + as: "author", }, { model: Like, - attributes: ['userId'] - } - ] - }) + attributes: ["userId"], + }, + ], + }); - if (!tweet) throw new Error("Tweet didn't exist!") - console.log(tweet) + if (!tweet) throw new Error("Tweet didn't exist!"); + console.log(tweet); - const tweetData = [tweet].map(t => ({ + const tweetData = [tweet].map((t) => ({ id: t.id, authorName: t.author.name, - authorAaccount: t.author.account, + authorAccount: t.author.account, authorAvatar: t.author.avatar, description: t.description, likeCount: t.likeCount, replyCount: t.replyCount, - isLiked: t.Likes.some(i => i.userId === userId), - createdAt: t.createdAt - })) - res.status(200).json(tweetData) + isLiked: t.Likes.some((i) => i.userId === userId), + createdAt: t.createdAt, + })); + res.status(200).json(tweetData); } catch (err) { - next(err) + next(err); } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (like) throw new Error('You have liked this tweet!') + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (like) throw new Error("You have liked this tweet!"); const createdLike = await Like.create({ userId, - tweetId - }) + tweetId, + }); res.status(200).json({ - status: 'success', + status: "success", data: createdLike, - isLiked: true - }) + isLiked: true, + }); } catch (err) { - next(err) + next(err); } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const getUser = helpers.getUser(req); + const userId = getUser.id; const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId - } - }) - ]) - if (!tweet) throw new Error("Tweet didn't exist!") - if (!like) throw new Error("You haven't liked this tweet!") + tweetId, + }, + }), + ]); + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!like) throw new Error("You haven't liked this tweet!"); await Like.destroy({ where: { userId, - tweetId - } - }) + tweetId, + }, + }); res.status(200).json({ - status: 'success', - isLiked: false - }) + status: "success", + isLiked: false, + }); } catch (err) { - next(err) + next(err); } }, createTweet: async (req, res, next) => { try { - const { description } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id - if (!description) throw new Error('文章內容不可為空白') - if (description.length > 140) throw new Error('文章內容不可超過 140 字') + const { description } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; + if (!description) throw new Error("文章內容不可為空白"); + if (description.length > 140) throw new Error("文章內容不可超過 140 字"); const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create tweet.', - data: createdTweet - }) + status: "success", + message: "Successfully create tweet.", + data: createdTweet, + }); } catch (err) { - next(err) + next(err); } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ { model: User, - as: 'author', - attributes: ['account', 'name', 'avatar'] - } - ] - } + as: "author", + attributes: ["account", "name", "avatar"], + }, + ], + }, ], - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], nest: true, - raw: true - }) + raw: true, + }); - if (!replies) throw new Error('This tweet has no replies') - console.log(replies) - const repliesData = replies.map(reply => ({ + if (!replies) throw new Error("This tweet has no replies"); + console.log(replies); + const repliesData = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -213,78 +213,78 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - res.status(200).json(repliesData) + res.status(200).json(repliesData); } catch (err) { - next(err) + next(err); } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id - const { comment } = req.body - const getUser = helpers.getUser(req) - const userId = getUser.id + const tweetId = req.params.tweet_id; + const { comment } = req.body; + const getUser = helpers.getUser(req); + const userId = getUser.id; - if (!comment) throw new Error('回覆內容不可為空白') + if (!comment) throw new Error("回覆內容不可為空白"); const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'successfully created reply', - replyData - }) + status: "success", + message: "successfully created reply", + replyData, + }); } catch (err) { - next(err) + next(err); } }, getLikes: async (req, res, next) => { try { - const tweetId = req.params.tweet_id + const tweetId = req.params.tweet_id; const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId + tweetId, }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ['password', 'introduction', 'cover'] } - } - ] - }) - ]) + attributes: { exclude: ["password", "introduction", "cover"] }, + }, + ], + }), + ]); - if (!tweet) throw new Error("Tweet didn't exist!") - if (!likes) throw new Error('NO ONE liked this tweet!') - const likedData = likes.map(like => ({ + if (!tweet) throw new Error("Tweet didn't exist!"); + if (!likes) throw new Error("NO ONE liked this tweet!"); + const likedData = likes.map((like) => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar - })) + likedUserAvatar: like.User.avatar, + })); res.status(200).json({ - status: 'success', - message: 'successfully get all the liked users', - likedData - }) + status: "success", + message: "successfully get all the liked users", + likedData, + }); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = tweetContorller +module.exports = tweetContorller; From 209b46cac286feca82b76bcec7bc0c0df2dc40e5 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 23:06:13 +0800 Subject: [PATCH 097/170] fix: admin signIn --- controllers/apis/admin-controller.js | 16 +- controllers/apis/tweet-controller.js | 274 +++++++++++++-------------- 2 files changed, 145 insertions(+), 145 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 8e1eccaaeb..9e78236218 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -121,18 +121,18 @@ const adminController = { throw new Error('Please enter account and password') } - const userData = await User.findOne({ where: { account } }) + const user = await User.findOne({ where: { account } }) - if (!userData) throw new Error('User does not exist') - if (userData.role === 'user') throw new Error('user permission denied') - if (!bcrypt.compareSync(password, userData.password)) { + if (!user) throw new Error('User does not exist') + if (user.role === 'user') throw new Error('user permission denied') + if (!bcrypt.compareSync(password, user.password)) { throw new Error('Incorrect password') } const payload = { - id: userData.id, - account: userData.account, - role: userData.role + id: user.id, + account: user.account, + role: user.role } const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: '30d' @@ -141,7 +141,7 @@ const adminController = { status: 'success', data: { token, - user: userData + user } }) } catch (err) { diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 183862c169..77f0636d72 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -1,41 +1,41 @@ -const { Tweet, Like, Reply, User } = require("../../models"); -const helpers = require("../../_helpers"); +const { Tweet, Like, Reply, User } = require('../../models') +const helpers = require('../../_helpers') const tweetContorller = { getTweets: async (req, res, next) => { try { - const getUser = helpers.getUser(req); - const userId = getUser.id; + const getUser = helpers.getUser(req) + const userId = getUser.id const options = { attributes: [ - "id", - "description", - "likeCount", - "replyCount", - "createdAt", + 'id', + 'description', + 'likeCount', + 'replyCount', + 'createdAt' ], - order: [["createdAt", "desc"]], + order: [['createdAt', 'desc']], subQuery: false, include: [ { model: User, - attributes: ["id", "account", "name", "avatar"], - as: "author", - where: { role: "user" }, + attributes: ['id', 'account', 'name', 'avatar'], + as: 'author', + where: { role: 'user' } }, { - model: Like, + model: Like }, { model: Reply, - as: "replies", - }, - ], - }; - const tweets = await Tweet.findAll(options); - console.log(tweets); + as: 'replies' + } + ] + } + const tweets = await Tweet.findAll(options) + console.log(tweets) - const dataTweets = tweets.map((tweet) => ({ + const dataTweets = tweets.map(tweet => ({ id: tweet.id, authorId: tweet.author.id, authorAccount: tweet.author.account, @@ -44,38 +44,38 @@ const tweetContorller = { description: tweet.description.substring(0, 140), likeCount: tweet.Likes.length, replyCount: tweet.replies.length, - isLiked: tweet.Likes.some((i) => i.userId === userId), - createdAt: tweet.createdAt, - })); - res.status(200).json(dataTweets); + isLiked: tweet.Likes.some(i => i.userId === userId), + createdAt: tweet.createdAt + })) + res.status(200).json(dataTweets) } catch (err) { - next(err); + next(err) } }, getTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const tweet = await Tweet.findOne({ where: { id: tweetId }, include: [ { model: User, - attributes: ["id", "account", "name", "avatar"], - as: "author", + attributes: ['id', 'account', 'name', 'avatar'], + as: 'author' }, { model: Like, - attributes: ["userId"], - }, - ], - }); + attributes: ['userId'] + } + ] + }) - if (!tweet) throw new Error("Tweet didn't exist!"); - console.log(tweet); + if (!tweet) throw new Error("Tweet didn't exist!") + console.log(tweet) - const tweetData = [tweet].map((t) => ({ + const tweetData = [tweet].map(t => ({ id: t.id, authorName: t.author.name, authorAccount: t.author.account, @@ -83,127 +83,127 @@ const tweetContorller = { description: t.description, likeCount: t.likeCount, replyCount: t.replyCount, - isLiked: t.Likes.some((i) => i.userId === userId), - createdAt: t.createdAt, - })); - res.status(200).json(tweetData); + isLiked: t.Likes.some(i => i.userId === userId), + createdAt: t.createdAt + })) + res.status(200).json(tweetData) } catch (err) { - next(err); + next(err) } }, likeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (like) throw new Error("You have liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (like) throw new Error('You have liked this tweet!') const createdLike = await Like.create({ userId, - tweetId, - }); + tweetId + }) res.status(200).json({ - status: "success", + status: 'success', data: createdLike, - isLiked: true, - }); + isLiked: true + }) } catch (err) { - next(err); + next(err) } }, unlikeTweet: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const getUser = helpers.getUser(req) + const userId = getUser.id const [tweet, like] = await Promise.all([ Tweet.findByPk(tweetId), Like.findOne({ where: { userId, - tweetId, - }, - }), - ]); - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!like) throw new Error("You haven't liked this tweet!"); + tweetId + } + }) + ]) + if (!tweet) throw new Error("Tweet didn't exist!") + if (!like) throw new Error("You haven't liked this tweet!") await Like.destroy({ where: { userId, - tweetId, - }, - }); + tweetId + } + }) res.status(200).json({ - status: "success", - isLiked: false, - }); + status: 'success', + isLiked: false + }) } catch (err) { - next(err); + next(err) } }, createTweet: async (req, res, next) => { try { - const { description } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; - if (!description) throw new Error("文章內容不可為空白"); - if (description.length > 140) throw new Error("文章內容不可超過 140 字"); + const { description } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id + if (!description) throw new Error('文章內容不可為空白') + if (description.length > 140) throw new Error('文章內容不可超過 140 字') const createdTweet = await Tweet.create({ userId, description, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create tweet.", - data: createdTweet, - }); + status: 'success', + message: 'Successfully create tweet.', + data: createdTweet + }) } catch (err) { - next(err); + next(err) } }, getReplies: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const replies = await Reply.findAll({ where: { tweetId }, include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ { model: User, - as: "author", - attributes: ["account", "name", "avatar"], - }, - ], - }, + as: 'author', + attributes: ['account', 'name', 'avatar'] + } + ] + } ], - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], nest: true, - raw: true, - }); + raw: true + }) - if (!replies) throw new Error("This tweet has no replies"); - console.log(replies); - const repliesData = replies.map((reply) => ({ + if (!replies) throw new Error('This tweet has no replies') + console.log(replies) + const repliesData = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -213,78 +213,78 @@ const tweetContorller = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(repliesData); + res.status(200).json(repliesData) } catch (err) { - next(err); + next(err) } }, createReply: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; - const { comment } = req.body; - const getUser = helpers.getUser(req); - const userId = getUser.id; + const tweetId = req.params.tweet_id + const { comment } = req.body + const getUser = helpers.getUser(req) + const userId = getUser.id - if (!comment) throw new Error("回覆內容不可為空白"); + if (!comment) throw new Error('回覆內容不可為空白') const replyData = await Reply.create({ tweetId, userId, comment, createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "successfully created reply", - replyData, - }); + status: 'success', + message: 'successfully created reply', + replyData + }) } catch (err) { - next(err); + next(err) } }, getLikes: async (req, res, next) => { try { - const tweetId = req.params.tweet_id; + const tweetId = req.params.tweet_id const [tweet, likes] = await Promise.all([ Tweet.findByPk(tweetId), Like.findAll({ where: { - tweetId, + tweetId }, nest: true, raw: true, include: [ { model: User, - attributes: { exclude: ["password", "introduction", "cover"] }, - }, - ], - }), - ]); + attributes: { exclude: ['password', 'introduction', 'cover'] } + } + ] + }) + ]) - if (!tweet) throw new Error("Tweet didn't exist!"); - if (!likes) throw new Error("NO ONE liked this tweet!"); - const likedData = likes.map((like) => ({ + if (!tweet) throw new Error("Tweet didn't exist!") + if (!likes) throw new Error('NO ONE liked this tweet!') + const likedData = likes.map(like => ({ likedId: like.id, likedTweetId: like.tweetId, likedUserId: like.User.id, likedUserName: like.User.name, likedUserAccount: like.User.account, - likedUserAvatar: like.User.avatar, - })); + likedUserAvatar: like.User.avatar + })) res.status(200).json({ - status: "success", - message: "successfully get all the liked users", - likedData, - }); + status: 'success', + message: 'successfully get all the liked users', + likedData + }) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = tweetContorller; +module.exports = tweetContorller From faed6026955842fdf21b5029fb1d6d2fd0a1c93a Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 28 Aug 2023 23:26:52 +0800 Subject: [PATCH 098/170] fix: test modify routes index.js --- routes/index.js | 138 ++++++++++++++++++++++++++++++++++------ routes/modules/admin.js | 2 +- 2 files changed, 120 insertions(+), 20 deletions(-) diff --git a/routes/index.js b/routes/index.js index 9410112ff8..2203aed5a4 100644 --- a/routes/index.js +++ b/routes/index.js @@ -8,38 +8,138 @@ const admin = require('./modules/admin') const userController = require('../controllers/apis/user-controller') const tweetController = require('../controllers/apis/tweet-controller') const followshipController = require('../controllers/apis/followship-controller') +const adminController = require('../controllers/apis/admin-controller') const { apiErrorHandler } = require('../middleware/error-handler') -const { authenticated, authenticatedAdmin, authenticatedUser } = require('../middleware/api-auth') +const { + authenticated, + authenticatedAdmin, + authenticatedUser +} = require('../middleware/api-auth') // api/admin +router.post('/api/admin/signin', adminController.signIn) router.use('/api/admin', authenticated, authenticatedAdmin, admin) // api/users router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) -router.put('/api/users/:id', authenticated, authenticatedUser, upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'cover', maxCount: 1 }]), userController.updateUser) -router.get('/api/users/:id/likes', authenticated, authenticatedUser, userController.getUserLikes) -router.get('/api/users/:id/followers', authenticated, authenticatedUser, userController.getUserFollowers) -router.get('/api/users/:id/followings', authenticated, authenticatedUser, userController.getUserFollowings) -router.get('/api/users/:id/tweets', authenticated, authenticatedUser, userController.getUserTweets) -router.get('/api/users/:id/replied_tweets', authenticated, authenticatedUser, userController.getUserReplies) -router.get('/api/users/:id', authenticated, authenticatedUser, userController.getUser) +router.put( + '/api/users/:id', + authenticated, + authenticatedUser, + upload.fields([ + { name: 'avatar', maxCount: 1 }, + { name: 'cover', maxCount: 1 } + ]), + userController.updateUser +) +router.get( + '/api/users/:id/likes', + authenticated, + authenticatedUser, + userController.getUserLikes +) +router.get( + '/api/users/:id/followers', + authenticated, + authenticatedUser, + userController.getUserFollowers +) +router.get( + '/api/users/:id/followings', + authenticated, + authenticatedUser, + userController.getUserFollowings +) +router.get( + '/api/users/:id/tweets', + authenticated, + authenticatedUser, + userController.getUserTweets +) +router.get( + '/api/users/:id/replied_tweets', + authenticated, + authenticatedUser, + userController.getUserReplies +) +router.get( + '/api/users/:id', + authenticated, + authenticatedUser, + userController.getUser +) // api/tweets -router.get('/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.getReplies) -router.post('/api/tweets/:tweet_id/replies', authenticated, authenticatedUser, tweetController.createReply) -router.get('/api/tweets/:tweet_id/likes', authenticated, authenticatedUser, tweetController.getLikes) -router.post('/api/tweets/:tweet_id/like', authenticated, authenticatedUser, tweetController.likeTweet) -router.post('/api/tweets/:tweet_id/unlike', authenticated, authenticatedUser, tweetController.unlikeTweet) -router.get('/api/tweets/:tweet_id', authenticated, authenticatedUser, tweetController.getTweet) -router.post('/api/tweets', authenticated, authenticatedUser, tweetController.createTweet) -router.get('/api/tweets', authenticated, authenticatedUser, tweetController.getTweets) +router.get( + '/api/tweets/:tweet_id/replies', + authenticated, + authenticatedUser, + tweetController.getReplies +) +router.post( + '/api/tweets/:tweet_id/replies', + authenticated, + authenticatedUser, + tweetController.createReply +) +router.get( + '/api/tweets/:tweet_id/likes', + authenticated, + authenticatedUser, + tweetController.getLikes +) +router.post( + '/api/tweets/:tweet_id/like', + authenticated, + authenticatedUser, + tweetController.likeTweet +) +router.post( + '/api/tweets/:tweet_id/unlike', + authenticated, + authenticatedUser, + tweetController.unlikeTweet +) +router.get( + '/api/tweets/:tweet_id', + authenticated, + authenticatedUser, + tweetController.getTweet +) +router.post( + '/api/tweets', + authenticated, + authenticatedUser, + tweetController.createTweet +) +router.get( + '/api/tweets', + authenticated, + authenticatedUser, + tweetController.getTweets +) // api/followship -router.delete('/api/followships/:following_id', authenticated, authenticatedUser, followshipController.unfollowUser) -router.get('/api/followships/top10', authenticated, authenticatedUser, followshipController.getTop10) -router.post('/api/followships', authenticated, authenticatedUser, followshipController.followUser) +router.delete( + '/api/followships/:following_id', + authenticated, + authenticatedUser, + followshipController.unfollowUser +) +router.get( + '/api/followships/top10', + authenticated, + authenticatedUser, + followshipController.getTop10 +) +router.post( + '/api/followships', + authenticated, + authenticatedUser, + followshipController.followUser +) router.use('/', apiErrorHandler) module.exports = router diff --git a/routes/modules/admin.js b/routes/modules/admin.js index a9fe756585..7f7a26b584 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -3,7 +3,7 @@ const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') const passport = require('passport') -router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) +// router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) router.get('/users', adminController.getUsers) router.delete('/tweets/:id', adminController.deleteTweet) From f1769838cfb198b69dd78b2366a6c3ed22a80284 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 29 Aug 2023 11:34:55 +0800 Subject: [PATCH 099/170] fix: get specific tweet bugs --- controllers/apis/tweet-controller.js | 11 +++++++---- routes/index.js | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 77f0636d72..5202893bb3 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -66,8 +66,11 @@ const tweetContorller = { as: 'author' }, { - model: Like, - attributes: ['userId'] + model: Like + }, + { + model: Reply, + as: 'replies' } ] }) @@ -81,8 +84,8 @@ const tweetContorller = { authorAccount: t.author.account, authorAvatar: t.author.avatar, description: t.description, - likeCount: t.likeCount, - replyCount: t.replyCount, + likeCount: tweet.Likes.length, + replyCount: tweet.replies.length, isLiked: t.Likes.some(i => i.userId === userId), createdAt: t.createdAt })) diff --git a/routes/index.js b/routes/index.js index 2203aed5a4..0e10e7dffe 100644 --- a/routes/index.js +++ b/routes/index.js @@ -19,7 +19,7 @@ const { // api/admin router.post('/api/admin/signin', adminController.signIn) -router.use('/api/admin', authenticated, authenticatedAdmin, admin) +// router.use('/api/admin', authenticated, authenticatedAdmin, admin) // api/users router.post('/api/users', userController.signUp) From 04e39f2a08009b66b0a0f7d932e1724e8b60631c Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 29 Aug 2023 14:29:55 +0800 Subject: [PATCH 100/170] fix: creatOneReply --- controllers/apis/tweet-controller.js | 55 +++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 5202893bb3..2787a63fe1 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -230,20 +230,63 @@ const tweetContorller = { const { comment } = req.body const getUser = helpers.getUser(req) const userId = getUser.id + const createdAt = new Date() + const updatedAt = new Date() if (!comment) throw new Error('回覆內容不可為空白') - const replyData = await Reply.create({ + const [reply, currentUser, tweet] = await Promise.all([ + Reply.create({ + tweetId, + userId, + comment, + createdAt, + updatedAt + }), + User.findOne({ + where: { id: userId }, + attributes: ['name', 'account', 'avatar'], + raw: true, + nest: true + }), + + Tweet.findOne({ + where: { id: tweetId }, + attributes: ['id'], + // next: true, + // raw: true, + include: { + model: User, + as: 'author', + attributes: ['account'] + } + }) + ]) + // const replyData = await Reply.create({ + // tweetId, + // userId, + // comment, + // createdAt: new Date(), + // updatedAt: new Date(), + // }); + console.log(reply, currentUser, tweet) + + const replyDatas = { + id: reply.dataValues.id, tweetId, userId, + userAvatar: currentUser.avatar, + userName: currentUser.name, + userAccount: currentUser.account, + authorAccount: tweet.author.account, comment, - createdAt: new Date(), - updatedAt: new Date() - }) - + createdAt, + updatedAt + } + console.log(replyDatas) res.status(200).json({ status: 'success', message: 'successfully created reply', - replyData + replyDatas }) } catch (err) { next(err) From 684c6acb180b6a75f0da479f8428dfcc5df44816 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 29 Aug 2023 14:43:05 +0800 Subject: [PATCH 101/170] fix: bugs --- controllers/apis/tweet-controller.js | 18 +++++------------- routes/index.js | 2 +- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 2787a63fe1..9a94aa69c9 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -252,8 +252,8 @@ const tweetContorller = { Tweet.findOne({ where: { id: tweetId }, attributes: ['id'], - // next: true, - // raw: true, + nest: true, + raw: true, include: { model: User, as: 'author', @@ -261,16 +261,8 @@ const tweetContorller = { } }) ]) - // const replyData = await Reply.create({ - // tweetId, - // userId, - // comment, - // createdAt: new Date(), - // updatedAt: new Date(), - // }); console.log(reply, currentUser, tweet) - - const replyDatas = { + const replyData = { id: reply.dataValues.id, tweetId, userId, @@ -282,11 +274,11 @@ const tweetContorller = { createdAt, updatedAt } - console.log(replyDatas) + console.log(replyData) res.status(200).json({ status: 'success', message: 'successfully created reply', - replyDatas + replyData }) } catch (err) { next(err) diff --git a/routes/index.js b/routes/index.js index 0e10e7dffe..903d1318b2 100644 --- a/routes/index.js +++ b/routes/index.js @@ -20,7 +20,7 @@ const { // api/admin router.post('/api/admin/signin', adminController.signIn) // router.use('/api/admin', authenticated, authenticatedAdmin, admin) - +router.use('/api/admin', admin) // api/users router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) From 6ffeff53309aff076e4d76edc9ee6c900b4ea390 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 29 Aug 2023 23:11:59 +0800 Subject: [PATCH 102/170] fix: cors use package --- app.js | 10 ++++++++-- routes/modules/admin.js | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index f817c51610..69d90e127c 100644 --- a/app.js +++ b/app.js @@ -7,10 +7,16 @@ const express = require('express') const bodyParser = require('body-parser') const routes = require('./routes') const passport = require('./config/passport') -const { CORSHeader } = require('./middleware/CORS-header') +const cors = require('cors') +const corsOptions = { + origin: '*', + methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', + allowedHeaders: ['Content-Type', 'Authorization'] +} const app = express() +app.use(cors(corsOptions)) // bodyparser設定 app.use(bodyParser.urlencoded({ extended: true })) app.use(bodyParser.json()) @@ -22,7 +28,7 @@ app.use('/upload', express.static(path.join(__dirname, 'upload'))) const port = process.env.PORT || 3000 -app.use('/', CORSHeader, routes) +app.use('/api', routes) app.get('/', (req, res) => res.send('Hello World!')) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 7f7a26b584..872a77fad0 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -9,6 +9,6 @@ router.get('/users', adminController.getUsers) router.delete('/tweets/:id', adminController.deleteTweet) router.get('/tweets', adminController.getTweets) -router.use('/', (req, res) => res.redirect('api/admin/users')) +// router.use('/', (req, res) => res.redirect('api/admin/users')) module.exports = router From 96082763d37af9ab023792e88e61275a2797c567 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 29 Aug 2023 23:15:56 +0800 Subject: [PATCH 103/170] fix: authenticated admin --- routes/index.js | 1 - routes/modules/admin.js | 16 +++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/routes/index.js b/routes/index.js index 903d1318b2..2173d15a4f 100644 --- a/routes/index.js +++ b/routes/index.js @@ -19,7 +19,6 @@ const { // api/admin router.post('/api/admin/signin', adminController.signIn) -// router.use('/api/admin', authenticated, authenticatedAdmin, admin) router.use('/api/admin', admin) // api/users router.post('/api/users', userController.signUp) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 872a77fad0..2b4dff7d5d 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -2,11 +2,21 @@ const express = require('express') const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') const passport = require('passport') - +const { authenticated, authenticatedAdmin } = require('../middleware/api-auth') // router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) -router.get('/users', adminController.getUsers) -router.delete('/tweets/:id', adminController.deleteTweet) +router.get( + '/users', + authenticated, + authenticatedAdmin, + adminController.getUsers +) +router.delete( + '/tweets/:id', + authenticated, + authenticatedAdmin, + adminController.deleteTweet +) router.get('/tweets', adminController.getTweets) // router.use('/', (req, res) => res.redirect('api/admin/users')) From 425837b9ba18d285de2e435b34f56453a2786905 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 29 Aug 2023 23:16:43 +0800 Subject: [PATCH 104/170] fix: bugs --- routes/modules/admin.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 2b4dff7d5d..2364388f23 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -17,7 +17,12 @@ router.delete( authenticatedAdmin, adminController.deleteTweet ) -router.get('/tweets', adminController.getTweets) +router.get( + '/tweets', + authenticated, + authenticatedAdmin, + adminController.getTweets +) // router.use('/', (req, res) => res.redirect('api/admin/users')) From cfda9c755c9ba5b5118a366b6ad613b119606b04 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Tue, 29 Aug 2023 23:24:49 +0800 Subject: [PATCH 105/170] merge --- controllers/apis/tweet-controller.js | 1 + routes/modules/admin.js | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 56b7e5ba08..9a94aa69c9 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -34,6 +34,7 @@ const tweetContorller = { } const tweets = await Tweet.findAll(options) console.log(tweets) + const dataTweets = tweets.map(tweet => ({ id: tweet.id, authorId: tweet.author.id, diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 7f7a26b584..4a82717b3e 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -2,12 +2,13 @@ const express = require('express') const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') const passport = require('passport') +const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') // router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) -router.get('/users', adminController.getUsers) -router.delete('/tweets/:id', adminController.deleteTweet) -router.get('/tweets', adminController.getTweets) +router.get('/users', authenticated, authenticatedAdmin, adminController.getUsers) +router.delete('/tweets/:id', authenticated, authenticatedAdmin, adminController.deleteTweet) +router.get('/tweets', authenticated, authenticatedAdmin, adminController.getTweets) router.use('/', (req, res) => res.redirect('api/admin/users')) From 772bfaa4a2f822750b66276c571cd262cbd045fe Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 29 Aug 2023 23:27:46 +0800 Subject: [PATCH 106/170] fix : bugs --- routes/modules/admin.js | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 2364388f23..e7cd6b0a53 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -1,29 +1,32 @@ -const express = require('express') -const router = express.Router() -const adminController = require('../../controllers/apis/admin-controller') -const passport = require('passport') -const { authenticated, authenticatedAdmin } = require('../middleware/api-auth') +const express = require("express"); +const router = express.Router(); +const adminController = require("../../controllers/apis/admin-controller"); +const passport = require("passport"); +const { + authenticated, + authenticatedAdmin, +} = require("../../middleware/api-auth"); // router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) router.get( - '/users', + "/users", authenticated, authenticatedAdmin, adminController.getUsers -) +); router.delete( - '/tweets/:id', + "/tweets/:id", authenticated, authenticatedAdmin, adminController.deleteTweet -) +); router.get( - '/tweets', + "/tweets", authenticated, authenticatedAdmin, adminController.getTweets -) +); // router.use('/', (req, res) => res.redirect('api/admin/users')) -module.exports = router +module.exports = router; From 6e835ab6f6ddeacfc30b5b5e054a9052a2e0c773 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Tue, 29 Aug 2023 23:46:53 +0800 Subject: [PATCH 107/170] fix : bugs --- app.js | 2 +- controllers/apis/user-controller.js | 1 + routes/modules/admin.js | 33 +++++++++++++---------- seeders/20230821044414-users-seed-file.js | 4 +-- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/app.js b/app.js index 69d90e127c..e6e382aaeb 100644 --- a/app.js +++ b/app.js @@ -8,6 +8,7 @@ const bodyParser = require('body-parser') const routes = require('./routes') const passport = require('./config/passport') const cors = require('cors') + const corsOptions = { origin: '*', methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', @@ -29,7 +30,6 @@ app.use('/upload', express.static(path.join(__dirname, 'upload'))) const port = process.env.PORT || 3000 app.use('/api', routes) -app.get('/', (req, res) => res.send('Hello World!')) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) module.exports = app diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 0a2233dfdf..be978428c3 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -124,6 +124,7 @@ const userController = { follow => follow.followingId === Number(id) ) } + console.log(user) res.status(200).json(user) } catch (err) { next(err) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index e7cd6b0a53..9fdc8a8a73 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -1,32 +1,37 @@ -const express = require("express"); -const router = express.Router(); -const adminController = require("../../controllers/apis/admin-controller"); -const passport = require("passport"); +const express = require('express') +const router = express.Router() +const adminController = require('../../controllers/apis/admin-controller') +const passport = require('passport') const { authenticated, - authenticatedAdmin, -} = require("../../middleware/api-auth"); -// router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) + authenticatedAdmin +} = require('../../middleware/api-auth') + +// router.post( +// "/login", +// passport.authenticate("jwt", { session: false }), +// adminController.signIn +// ); router.get( - "/users", + '/users', authenticated, authenticatedAdmin, adminController.getUsers -); +) router.delete( - "/tweets/:id", + '/tweets/:id', authenticated, authenticatedAdmin, adminController.deleteTweet -); +) router.get( - "/tweets", + '/tweets', authenticated, authenticatedAdmin, adminController.getTweets -); +) // router.use('/', (req, res) => res.redirect('api/admin/users')) -module.exports = router; +module.exports = router diff --git a/seeders/20230821044414-users-seed-file.js b/seeders/20230821044414-users-seed-file.js index 84f60a1ce9..ffdc9d3b13 100644 --- a/seeders/20230821044414-users-seed-file.js +++ b/seeders/20230821044414-users-seed-file.js @@ -13,10 +13,10 @@ module.exports = { role: 'admin', name: 'Admin', account: 'root', - avatar: `https://loremflickr.com/320/240/man/?random=${ + avatar: `https://loremflickr.com/150/150/boy/?random=${ Math.random() * 100 }`, - cover: `https://loremflickr.com/1440/480/city/?random=${ + cover: `https://loremflickr.com/300/200/city/?random=${ Math.random() * 100 }`, introduction: faker.lorem.text().substring(0, 160), From d18646202a8df607493b5c1e1a88ecce29f7d2b6 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 30 Aug 2023 00:10:59 +0800 Subject: [PATCH 108/170] fix: delete corsOptions --- app.js | 12 ++++++------ middleware/CORS-header.js | 18 ------------------ routes/index.js | 9 +-------- routes/modules/admin.js | 9 --------- 4 files changed, 7 insertions(+), 41 deletions(-) delete mode 100644 middleware/CORS-header.js diff --git a/app.js b/app.js index e6e382aaeb..383468627d 100644 --- a/app.js +++ b/app.js @@ -9,15 +9,15 @@ const routes = require('./routes') const passport = require('./config/passport') const cors = require('cors') -const corsOptions = { - origin: '*', - methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', - allowedHeaders: ['Content-Type', 'Authorization'] -} +// const corsOptions = { +// origin: '*', +// methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', +// allowedHeaders: ['Content-Type', 'Authorization'] +// } const app = express() -app.use(cors(corsOptions)) +app.use(cors()) // bodyparser設定 app.use(bodyParser.urlencoded({ extended: true })) app.use(bodyParser.json()) diff --git a/middleware/CORS-header.js b/middleware/CORS-header.js deleted file mode 100644 index 46bf5cccca..0000000000 --- a/middleware/CORS-header.js +++ /dev/null @@ -1,18 +0,0 @@ -const CORSHeader = (req, res, next) => { - res.header('Access-Control-Allow-Origin', '*') - res.header( - 'Access-Control-Allow-Headers', - 'Origin, X-Requested-With, Content-Type, Accept, Authorization' - ) - if (req.method === 'OPTIONS') { - res.header( - 'Access-Control-Allow-Methods', - 'GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS' - ) - } - return next() -} - -module.exports = { - CORSHeader -} diff --git a/routes/index.js b/routes/index.js index 2173d15a4f..123c93a383 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,21 +1,14 @@ const express = require('express') const router = express.Router() -// const storage = multer.memoryStorage() const upload = require('../middleware/multer') - const admin = require('./modules/admin') - const userController = require('../controllers/apis/user-controller') const tweetController = require('../controllers/apis/tweet-controller') const followshipController = require('../controllers/apis/followship-controller') const adminController = require('../controllers/apis/admin-controller') const { apiErrorHandler } = require('../middleware/error-handler') -const { - authenticated, - authenticatedAdmin, - authenticatedUser -} = require('../middleware/api-auth') +const { authenticated, authenticatedUser } = require('../middleware/api-auth') // api/admin router.post('/api/admin/signin', adminController.signIn) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 9fdc8a8a73..a023d9baa4 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -1,18 +1,11 @@ const express = require('express') const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') -const passport = require('passport') const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') -// router.post( -// "/login", -// passport.authenticate("jwt", { session: false }), -// adminController.signIn -// ); - router.get( '/users', authenticated, @@ -32,6 +25,4 @@ router.get( adminController.getTweets ) -// router.use('/', (req, res) => res.redirect('api/admin/users')) - module.exports = router From 305f6a1ddcbc256c92a998a67580aaad918398ef Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 30 Aug 2023 00:21:57 +0800 Subject: [PATCH 109/170] fix: corsOptions OPTIONS --- app.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app.js b/app.js index 383468627d..44f9203b82 100644 --- a/app.js +++ b/app.js @@ -9,15 +9,15 @@ const routes = require('./routes') const passport = require('./config/passport') const cors = require('cors') -// const corsOptions = { -// origin: '*', -// methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', -// allowedHeaders: ['Content-Type', 'Authorization'] -// } +const corsOptions = { + origin: '*', + methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS', + allowedHeaders: ['Content-Type', 'Authorization'] +} const app = express() -app.use(cors()) +app.use(cors(corsOptions)) // bodyparser設定 app.use(bodyParser.urlencoded({ extended: true })) app.use(bodyParser.json()) From 6a82e51c1b3010c188bc73d11da49e98d782e7a1 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Wed, 30 Aug 2023 01:57:26 +0800 Subject: [PATCH 110/170] fix: cors --- app.js | 17 ++++++----------- routes/index.js | 1 - routes/modules/admin.js | 10 +--------- 3 files changed, 7 insertions(+), 21 deletions(-) diff --git a/app.js b/app.js index e6e382aaeb..1b9cb8453e 100644 --- a/app.js +++ b/app.js @@ -1,23 +1,17 @@ if (process.NODE_ENV !== 'production') { require('dotenv').config() } - +const cors = require('cors') const path = require('path') const express = require('express') const bodyParser = require('body-parser') const routes = require('./routes') const passport = require('./config/passport') -const cors = require('cors') - -const corsOptions = { - origin: '*', - methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', - allowedHeaders: ['Content-Type', 'Authorization'] -} const app = express() -app.use(cors(corsOptions)) +app.use(cors()) + // bodyparser設定 app.use(bodyParser.urlencoded({ extended: true })) app.use(bodyParser.json()) @@ -27,9 +21,10 @@ app.use(passport.session()) app.use('/upload', express.static(path.join(__dirname, 'upload'))) -const port = process.env.PORT || 3000 +const port = process.env.PORT || 3001 + +app.use(routes) -app.use('/api', routes) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) module.exports = app diff --git a/routes/index.js b/routes/index.js index 2173d15a4f..9a2945b0e2 100644 --- a/routes/index.js +++ b/routes/index.js @@ -13,7 +13,6 @@ const adminController = require('../controllers/apis/admin-controller') const { apiErrorHandler } = require('../middleware/error-handler') const { authenticated, - authenticatedAdmin, authenticatedUser } = require('../middleware/api-auth') diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 9fdc8a8a73..f6d29d27ef 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -1,18 +1,12 @@ const express = require('express') const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') -const passport = require('passport') + const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') -// router.post( -// "/login", -// passport.authenticate("jwt", { session: false }), -// adminController.signIn -// ); - router.get( '/users', authenticated, @@ -32,6 +26,4 @@ router.get( adminController.getTweets ) -// router.use('/', (req, res) => res.redirect('api/admin/users')) - module.exports = router From 159cd4daffcc67c7c9ddbb7b6a4a5c84a431edfa Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Wed, 30 Aug 2023 02:45:04 +0800 Subject: [PATCH 111/170] fix: admin login can get data now --- middleware/CORS-header.js | 18 ------------------ routes/index.js | 2 +- routes/modules/admin.js | 2 ++ 3 files changed, 3 insertions(+), 19 deletions(-) delete mode 100644 middleware/CORS-header.js diff --git a/middleware/CORS-header.js b/middleware/CORS-header.js deleted file mode 100644 index 46bf5cccca..0000000000 --- a/middleware/CORS-header.js +++ /dev/null @@ -1,18 +0,0 @@ -const CORSHeader = (req, res, next) => { - res.header('Access-Control-Allow-Origin', '*') - res.header( - 'Access-Control-Allow-Headers', - 'Origin, X-Requested-With, Content-Type, Accept, Authorization' - ) - if (req.method === 'OPTIONS') { - res.header( - 'Access-Control-Allow-Methods', - 'GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS' - ) - } - return next() -} - -module.exports = { - CORSHeader -} diff --git a/routes/index.js b/routes/index.js index 9a2945b0e2..24e3c220a4 100644 --- a/routes/index.js +++ b/routes/index.js @@ -17,8 +17,8 @@ const { } = require('../middleware/api-auth') // api/admin -router.post('/api/admin/signin', adminController.signIn) router.use('/api/admin', admin) + // api/users router.post('/api/users', userController.signUp) router.post('/api/users/signin', userController.signIn) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index f6d29d27ef..058c79f613 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -7,6 +7,8 @@ const { authenticatedAdmin } = require('../../middleware/api-auth') +router.post('/signin', adminController.signIn) + router.get( '/users', authenticated, From cd949f44627b5ece3664440257b670843b751c3e Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Wed, 30 Aug 2023 02:48:17 +0800 Subject: [PATCH 112/170] style: do some modification --- app.js | 2 +- routes/index.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app.js b/app.js index 1b9cb8453e..f0795b108d 100644 --- a/app.js +++ b/app.js @@ -21,7 +21,7 @@ app.use(passport.session()) app.use('/upload', express.static(path.join(__dirname, 'upload'))) -const port = process.env.PORT || 3001 +const port = process.env.PORT || 3000 app.use(routes) diff --git a/routes/index.js b/routes/index.js index 24e3c220a4..d116fbf88d 100644 --- a/routes/index.js +++ b/routes/index.js @@ -8,7 +8,6 @@ const admin = require('./modules/admin') const userController = require('../controllers/apis/user-controller') const tweetController = require('../controllers/apis/tweet-controller') const followshipController = require('../controllers/apis/followship-controller') -const adminController = require('../controllers/apis/admin-controller') const { apiErrorHandler } = require('../middleware/error-handler') const { From fbc8d2dd2a724f0f2cac2711ec76abb77cfefb95 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 30 Aug 2023 15:30:02 +0800 Subject: [PATCH 113/170] fix: isfollowed --- controllers/apis/user-controller.js | 37 +++++++++++++---------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index be978428c3..9bf5820b09 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -311,34 +311,33 @@ const userController = { const userTweets = await Tweet.findAll({ where: { userId: id }, order: [['createdAt', 'DESC']], - // attributes:['id','description', [ - // sequelize.literal( - // '(SELECT COUNT(DISTINCT id) FROM Like WHERE user_id = User.id)' - // ), - // 'totalFollowers' - // ],] include: [ { model: User, as: 'author', attributes: { exclude: ['password'] } + }, + { + model: Like + }, + { + model: Reply, + as: 'replies' } - // { - // model:Like, - // as - // } ] }) - + console.log(userTweets) const userTweetsData = userTweets.map(tweet => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, tweetBelongerAvatar: tweet.author.avatar, - tweetLikeCount: tweet.likeCount, - tweetReplyCount: tweet.replyCount, + // tweetLikeCount: tweet.likeCount, + // tweetReplyCount: tweet.replyCount, description: tweet.description, - createdAt: tweet.createdAt + createdAt: tweet.createdAt, + replyCount: tweet.Likes.length, + likeCount: tweet.replies.length })) res.status(200).json(userTweetsData) @@ -379,14 +378,10 @@ const userController = { raw: true, nest: true }) - - const userFollowersData = followers.map(follower => { - return { - ...follower - } + followers.forEach(follower => { + follower.isFollowed = !!follower.isFollowed }) - - res.status(200).json(userFollowersData) + res.status(200).json(followers) } catch (err) { next(err) } From a37fe7e2548bd34a85be2663c760e74d7eb5459f Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 30 Aug 2023 15:31:23 +0800 Subject: [PATCH 114/170] fix: isFollowing boolean --- controllers/apis/user-controller.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 9bf5820b09..6aabab2d29 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -418,14 +418,10 @@ const userController = { raw: true, nest: true }) - - const userFollowersData = following.map(follower => { - return { - ...follower - } + following.forEach(following => { + following.isFollowed = !!following.isFollowed }) - - res.status(200).json(userFollowersData) + res.status(200).json(following) } catch (err) { next(err) } From aeab7a268e8fe7f8d1f170ab1ebafb4cd9120294 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 30 Aug 2023 21:34:47 +0800 Subject: [PATCH 115/170] fix: isFollowed --- controllers/apis/user-controller.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 6aabab2d29..218e3685df 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -378,10 +378,12 @@ const userController = { raw: true, nest: true }) - followers.forEach(follower => { - follower.isFollowed = !!follower.isFollowed - }) - res.status(200).json(followers) + const followersData = followers.map(item => ({ + ...item, + isFollowed: item.isFollowed === 1 + })) + + res.status(200).json(followersData) } catch (err) { next(err) } @@ -418,10 +420,13 @@ const userController = { raw: true, nest: true }) - following.forEach(following => { - following.isFollowed = !!following.isFollowed - }) - res.status(200).json(following) + + const followings = following.map(item => ({ + ...item, + isFollowed: item.isFollowed === 1 + })) + console.log(followings) + res.status(200).json(followings) } catch (err) { next(err) } From ebe1cef0331530ba08a8c973dfbab3371fc875ba Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 30 Aug 2023 21:43:16 +0800 Subject: [PATCH 116/170] fix : reply count and like count --- controllers/apis/user-controller.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 218e3685df..4828a52631 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -270,12 +270,21 @@ const userController = { { model: Tweet, as: 'likedTweet', + raw: true, + nest: true, attributes: { exclude: ['password'] }, include: [ { model: User, as: 'author', attributes: ['account', 'name', 'avatar'] + }, + { + model: Like + }, + { + model: Reply, + as: 'replies' } ] } @@ -285,16 +294,16 @@ const userController = { if (likeTweets.length === 0) { throw new Error('the user did not like any tweet') } - + console.log(likeTweets) const likeTweetsData = likeTweets.map(like => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, tweetBelongerAvatar: like.likedTweet.author.avatar, - tweetLikeCount: like.likedTweet.likeCount, - tweetReplyCount: like.likedTweet.replyCount, tweetContent: like.likedTweet.description, - createdAt: like.createdAt + createdAt: like.createdAt, + replyCount: like.likedTweet.Likes.length, + likeCount: like.likedTweet.replies.length })) res.status(200).json(likeTweetsData) @@ -332,8 +341,6 @@ const userController = { tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, tweetBelongerAvatar: tweet.author.avatar, - // tweetLikeCount: tweet.likeCount, - // tweetReplyCount: tweet.replyCount, description: tweet.description, createdAt: tweet.createdAt, replyCount: tweet.Likes.length, From 324ea383a242feaef9c46ab5a0b28344d716ad20 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 30 Aug 2023 23:10:23 +0800 Subject: [PATCH 117/170] fix: signup error handler should send response to frontend --- controllers/apis/user-controller.js | 446 ++++++++++++++-------------- middleware/error-handler.js | 30 +- 2 files changed, 250 insertions(+), 226 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 4828a52631..72e0570820 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,33 +1,33 @@ -const bcrypt = require('bcryptjs') -const jwt = require('jsonwebtoken') -const sequelize = require('sequelize') -const { imgurFileHandler } = require('../../helpers/file-helpers') +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken"); +const sequelize = require("sequelize"); +const { imgurFileHandler } = require("../../helpers/file-helpers"); -const db = require('../../models') -const helpers = require('../../_helpers') +const db = require("../../models"); +const helpers = require("../../_helpers"); -const { User, Tweet, Reply, Followship, Like } = db -const { Op } = require('sequelize') +const { User, Tweet, Reply, Followship, Like } = db; +const { Op } = require("sequelize"); const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body + const { account, name, email, password, checkPassword } = req.body; if (!account || !name || !email || !password || !checkPassword) { - throw new Error('all the blanks are required') + throw new Error("all the blanks are required"); } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }] - } - }) + [Op.or]: [{ email }, { account }], + }, + }); if (user) { - if (user.account === account) throw new Error('account 已重複註冊!') - if (user.email === email) throw new Error('email 已重複註冊!') + if (user.account === account) throw new Error("account 已重複註冊!"); + if (user.email === email) throw new Error("email 已重複註冊!"); } const createdUser = await User.create({ @@ -35,104 +35,104 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: 'https://picsum.photos/100/100', - cover: 'https://picsum.photos/id/237/700/400', - role: 'user', + avatar: "https://picsum.photos/100/100", + cover: "https://picsum.photos/id/237/700/400", + role: "user", createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create user.', - data: createdUser - }) + status: "success", + message: "Successfully create user.", + data: createdUser, + }); } catch (err) { - next(err) + next(err); } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body + const { account, password } = req.body; if (!account || !password) { - throw new Error('Please enter account and password') + throw new Error("Please enter account and password"); } - const user = await User.findOne({ where: { account } }) - if (!user) throw new Error('User does not exist') - if (user.role === 'admin') throw new Error('admin permission denied') + const user = await User.findOne({ where: { account } }); + if (!user) throw new Error("User does not exist"); + if (user.role === "admin") throw new Error("admin permission denied"); if (!bcrypt.compareSync(password, user.password)) { - throw new Error('Incorrect password') + throw new Error("Incorrect password"); } const payload = { id: user.id, account: user.account, - role: user.role - } + role: user.role, + }; const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: '30d' - }) - const userId = user.toJSON().id + expiresIn: "30d", + }); + const userId = user.toJSON().id; res.status(200).json({ - status: 'success', + status: "success", data: { token, - userId - } - }) + userId, + }, + }); } catch (err) { - next(err) + next(err); } }, getUser: async (req, res, next) => { try { - const { id } = req.params - const currentUserId = helpers.getUser(req).id + const { id } = req.params; + const currentUserId = helpers.getUser(req).id; const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id } + where: { UserId: id }, }), Followship.count({ - where: { followerId: id } + where: { followerId: id }, }), Followship.count({ - where: { followingId: id } - }) - ]) + where: { followingId: id }, + }), + ]); if (!user) { return res .status(401) - .json({ status: 'error', message: 'This user does not exist' }) + .json({ status: "error", message: "This user does not exist" }); } - delete user.password - user.tweetCount = tweetCount - user.followerCount = followerCount - user.followingCount = followingCount + delete user.password; + user.tweetCount = tweetCount; + user.followerCount = followerCount; + user.followingCount = followingCount; if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); user.isFollowed = checkUserFollowing.some( - follow => follow.followingId === Number(id) - ) + (follow) => follow.followingId === Number(id) + ); } - console.log(user) - res.status(200).json(user) + console.log(user); + res.status(200).json(user); } catch (err) { - next(err) + next(err); } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id + const userId = req.params.id; const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -141,23 +141,23 @@ const userController = { include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ - { model: User, as: 'author', attributes: ['account', 'name'] } - ] - } + { model: User, as: "author", attributes: ["account", "name"] }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true - }) - ]) + order: [["createdAt", "DESC"]], + nest: true, + }), + ]); - const userRepliesResult = replies.map(reply => ({ + const userRepliesResult = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -167,76 +167,76 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - res.status(200).json(userRepliesResult) + res.status(200).json(userRepliesResult); } catch (err) { - next(err) + next(err); } }, updateUser: async (req, res, next) => { try { - const { id } = req.params - const { account, name, email, password, introduction } = req.body + const { id } = req.params; + const { account, name, email, password, introduction } = req.body; - const user = await User.findByPk(id) + const user = await User.findByPk(id); if (!user) { return res.status(401).json({ - status: 'error', - message: 'This user does not exist' - }) + status: "error", + message: "This user does not exist", + }); } - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; if (!currentUserId) { - throw new Error('Current user ID is missing') + throw new Error("Current user ID is missing"); } if (currentUserId !== Number(id)) { - throw new Error('Cannot edit other users profile') + throw new Error("Cannot edit other users profile"); } if (name && name.length > 50) { - throw new Error('the length of name should less than 50 characters') + throw new Error("the length of name should less than 50 characters"); } if (introduction && introduction.length > 160) { throw new Error( - 'the length of introduction should less than 160 characters' - ) + "the length of introduction should less than 160 characters" + ); } if (account) { const userByAccount = await User.findOne({ where: { account }, raw: true, - nest: true - }) + nest: true, + }); if (userByAccount && userByAccount.account === account) { - throw new Error('account 已重複註冊!') + throw new Error("account 已重複註冊!"); } } if (email) { - const userByEmail = await User.findOne({ where: { email } }) + const userByEmail = await User.findOne({ where: { email } }); if (userByEmail && userByEmail.email === email) { - throw new Error('email 已重複註冊!') + throw new Error("email 已重複註冊!"); } } - const { files } = req + const { files } = req; - let newAvatar = '' - let newCover = '' + let newAvatar = ""; + let newCover = ""; - if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { - newAvatar = await imgurFileHandler(files.avatar[0]) + if (files && files.avatar && files.avatar[0].fieldname === "avatar") { + newAvatar = await imgurFileHandler(files.avatar[0]); } - if (files && files.cover && files.cover[0].fieldname === 'cover') { - newCover = await imgurFileHandler(files.cover[0]) + if (files && files.cover && files.cover[0].fieldname === "cover") { + newCover = await imgurFileHandler(files.cover[0]); } await user.update({ @@ -246,97 +246,113 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover - }) + cover: newCover || user.cover, + }); res.status(200).json({ - status: 'success', - message: 'Successfully update user.', - data: user - }) + status: "success", + message: "Successfully update user.", + data: user, + }); } catch (err) { - next(err) + next(err); } }, getUserLikes: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') - - const likeTweets = await Like.findAll({ + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); + + // const likeTweets = await Like.findAll({ + // where: { userId: id }, + // order: [["createdAt", "DESC"]], + // include: [ + // { + // model: Tweet, + // as: "likedTweet", + // raw: true, + // nest: true, + // attributes: { exclude: ["password"] }, + // include: [ + // { + // model: User, + // as: "author", + // attributes: ["account", "name", "avatar"], + // }, + // { + // model: Like, + // }, + // { + // model: Reply, + // as: "replies", + // }, + // ], + // }, + // ], + // }); + const likedTweets = await Tweet.findAll({ where: { userId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { - model: Tweet, - as: 'likedTweet', - raw: true, - nest: true, - attributes: { exclude: ['password'] }, - include: [ - { - model: User, - as: 'author', - attributes: ['account', 'name', 'avatar'] - }, - { - model: Like - }, - { - model: Reply, - as: 'replies' - } - ] - } - ] - }) - - if (likeTweets.length === 0) { - throw new Error('the user did not like any tweet') + model: User, + as: "author", + attributes: { exclude: ["password"] }, + }, + { + model: Like, + }, + { + model: Reply, + as: "replies", + }, + ], + }); + if (likedTweets.length === 0) { + throw new Error("the user did not like any tweet"); } - console.log(likeTweets) - const likeTweetsData = likeTweets.map(like => ({ - TweetId: like.likedTweet.id, - tweetBelongerName: like.likedTweet.author.name, - tweetBelongerAccount: like.likedTweet.author.account, - tweetBelongerAvatar: like.likedTweet.author.avatar, - tweetContent: like.likedTweet.description, - createdAt: like.createdAt, - replyCount: like.likedTweet.Likes.length, - likeCount: like.likedTweet.replies.length - })) - - res.status(200).json(likeTweetsData) + console.log(likedTweets); + // const likedTweetsData = likeTweets.map((tweet) => ({ + // TweetId: tweet.likedTweet.id, + // tweetBelongerName: tweet.likedTweet.author.name, + // tweetBelongerAccount: tweet.likedTweet.author.account, + // tweetBelongerAvatar: tweet.likedTweet.author.avatar, + // tweetContent: tweet.likedTweet.description, + // createdAt: tweet.createdAt, + // replyCount: tweet.likedTweet.Likes.length, + // likeCount: tweet.likedTweet.replies.length, + // })); + res.status(200).json(likedTweets); } catch (err) { - next(err) + next(err); } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); const userTweets = await Tweet.findAll({ where: { userId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: User, - as: 'author', - attributes: { exclude: ['password'] } + as: "author", + attributes: { exclude: ["password"] }, }, { - model: Like + model: Like, }, { model: Reply, - as: 'replies' - } - ] - }) - console.log(userTweets) - const userTweetsData = userTweets.map(tweet => ({ + as: "replies", + }, + ], + }); + console.log(userTweets); + const userTweetsData = userTweets.map((tweet) => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -344,100 +360,100 @@ const userController = { description: tweet.description, createdAt: tweet.createdAt, replyCount: tweet.Likes.length, - likeCount: tweet.replies.length - })) + likeCount: tweet.replies.length, + })); - res.status(200).json(userTweetsData) + res.status(200).json(userTweetsData); } catch (err) { - next(err) + next(err); } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; const followers = await Followship.findAll({ where: { followingId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: User, - as: 'follower', - attributes: { exclude: ['password'] } - } + as: "follower", + attributes: { exclude: ["password"] }, + }, ], attributes: [ - 'followerId', - 'followingId', - 'createdAt', - 'updatedAt', + "followerId", + "followingId", + "createdAt", + "updatedAt", [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - 'isFollowed' - ] + "isFollowed", + ], ], raw: true, - nest: true - }) - const followersData = followers.map(item => ({ + nest: true, + }); + const followersData = followers.map((item) => ({ ...item, - isFollowed: item.isFollowed === 1 - })) + isFollowed: item.isFollowed === 1, + })); - res.status(200).json(followersData) + res.status(200).json(followersData); } catch (err) { - next(err) + next(err); } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') - const currentUserId = helpers.getUser(req).id + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); + const currentUserId = helpers.getUser(req).id; const following = await Followship.findAll({ where: { followerId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], include: [ { model: User, - as: 'following', - attributes: { exclude: ['password'] } - } + as: "following", + attributes: { exclude: ["password"] }, + }, ], attributes: [ - 'followerId', - 'followingId', - 'createdAt', - 'updatedAt', + "followerId", + "followingId", + "createdAt", + "updatedAt", [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - 'isFollowed' - ] + "isFollowed", + ], ], raw: true, - nest: true - }) + nest: true, + }); - const followings = following.map(item => ({ + const followings = following.map((item) => ({ ...item, - isFollowed: item.isFollowed === 1 - })) - console.log(followings) - res.status(200).json(followings) + isFollowed: item.isFollowed === 1, + })); + console.log(followings); + res.status(200).json(followings); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = userController +module.exports = userController; diff --git a/middleware/error-handler.js b/middleware/error-handler.js index 360dbdf84f..edcd1ee3b7 100644 --- a/middleware/error-handler.js +++ b/middleware/error-handler.js @@ -1,16 +1,24 @@ module.exports = { - apiErrorHandler (err, req, res, next) { + apiErrorHandler(err, req, res, next) { if (err instanceof Error) { - res.status(err.status || 500).json({ - status: 'error', - message: `${err.name}: ${err.message}` - }) + if (err.message === "帳號不存在") { + return res.status(200).json({ + status: "error", + statusCode: "404", + message: `${err.message}`, + }); + } + res.status(200).json({ + status: "error", + statusCode: "400", + message: `${err.message}`, + }); } else { res.status(500).json({ - status: 'error', - message: `${err}` - }) + status: "error", + message: `${err}`, + }); } - next(err) - } -} + next(err); + }, +}; From 62eeb7b2e247a574a7bdf742608f4294f1574425 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 30 Aug 2023 23:14:20 +0800 Subject: [PATCH 118/170] fix: get user liked tweets --- controllers/apis/user-controller.js | 390 ++++++++++++++-------------- middleware/error-handler.js | 32 +-- 2 files changed, 211 insertions(+), 211 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 72e0570820..7140ea8ed8 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,33 +1,33 @@ -const bcrypt = require("bcryptjs"); -const jwt = require("jsonwebtoken"); -const sequelize = require("sequelize"); -const { imgurFileHandler } = require("../../helpers/file-helpers"); +const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') +const sequelize = require('sequelize') +const { imgurFileHandler } = require('../../helpers/file-helpers') -const db = require("../../models"); -const helpers = require("../../_helpers"); +const db = require('../../models') +const helpers = require('../../_helpers') -const { User, Tweet, Reply, Followship, Like } = db; -const { Op } = require("sequelize"); +const { User, Tweet, Reply, Followship, Like } = db +const { Op } = require('sequelize') const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body; + const { account, name, email, password, checkPassword } = req.body if (!account || !name || !email || !password || !checkPassword) { - throw new Error("all the blanks are required"); + throw new Error('all the blanks are required') } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }], - }, - }); + [Op.or]: [{ email }, { account }] + } + }) if (user) { - if (user.account === account) throw new Error("account 已重複註冊!"); - if (user.email === email) throw new Error("email 已重複註冊!"); + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') } const createdUser = await User.create({ @@ -35,104 +35,104 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: "https://picsum.photos/100/100", - cover: "https://picsum.photos/id/237/700/400", - role: "user", + avatar: 'https://picsum.photos/100/100', + cover: 'https://picsum.photos/id/237/700/400', + role: 'user', createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create user.", - data: createdUser, - }); + status: 'success', + message: 'Successfully create user.', + data: createdUser + }) } catch (err) { - next(err); + next(err) } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body; + const { account, password } = req.body if (!account || !password) { - throw new Error("Please enter account and password"); + throw new Error('Please enter account and password') } - const user = await User.findOne({ where: { account } }); - if (!user) throw new Error("User does not exist"); - if (user.role === "admin") throw new Error("admin permission denied"); + const user = await User.findOne({ where: { account } }) + if (!user) throw new Error('User does not exist') + if (user.role === 'admin') throw new Error('admin permission denied') if (!bcrypt.compareSync(password, user.password)) { - throw new Error("Incorrect password"); + throw new Error('Incorrect password') } const payload = { id: user.id, account: user.account, - role: user.role, - }; + role: user.role + } const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "30d", - }); - const userId = user.toJSON().id; + expiresIn: '30d' + }) + const userId = user.toJSON().id res.status(200).json({ - status: "success", + status: 'success', data: { token, - userId, - }, - }); + userId + } + }) } catch (err) { - next(err); + next(err) } }, getUser: async (req, res, next) => { try { - const { id } = req.params; - const currentUserId = helpers.getUser(req).id; + const { id } = req.params + const currentUserId = helpers.getUser(req).id const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id }, + where: { UserId: id } }), Followship.count({ - where: { followerId: id }, + where: { followerId: id } }), Followship.count({ - where: { followingId: id }, - }), - ]); + where: { followingId: id } + }) + ]) if (!user) { return res .status(401) - .json({ status: "error", message: "This user does not exist" }); + .json({ status: 'error', message: 'This user does not exist' }) } - delete user.password; - user.tweetCount = tweetCount; - user.followerCount = followerCount; - user.followingCount = followingCount; + delete user.password + user.tweetCount = tweetCount + user.followerCount = followerCount + user.followingCount = followingCount if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) user.isFollowed = checkUserFollowing.some( - (follow) => follow.followingId === Number(id) - ); + follow => follow.followingId === Number(id) + ) } - console.log(user); - res.status(200).json(user); + console.log(user) + res.status(200).json(user) } catch (err) { - next(err); + next(err) } }, getUserReplies: async (req, res, next) => { try { - const userId = req.params.id; + const userId = req.params.id const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -141,23 +141,23 @@ const userController = { include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ - { model: User, as: "author", attributes: ["account", "name"] }, - ], - }, + { model: User, as: 'author', attributes: ['account', 'name'] } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, - }), - ]); + order: [['createdAt', 'DESC']], + nest: true + }) + ]) - const userRepliesResult = replies.map((reply) => ({ + const userRepliesResult = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -167,76 +167,76 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(userRepliesResult); + res.status(200).json(userRepliesResult) } catch (err) { - next(err); + next(err) } }, updateUser: async (req, res, next) => { try { - const { id } = req.params; - const { account, name, email, password, introduction } = req.body; + const { id } = req.params + const { account, name, email, password, introduction } = req.body - const user = await User.findByPk(id); + const user = await User.findByPk(id) if (!user) { return res.status(401).json({ - status: "error", - message: "This user does not exist", - }); + status: 'error', + message: 'This user does not exist' + }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id if (!currentUserId) { - throw new Error("Current user ID is missing"); + throw new Error('Current user ID is missing') } if (currentUserId !== Number(id)) { - throw new Error("Cannot edit other users profile"); + throw new Error('Cannot edit other users profile') } if (name && name.length > 50) { - throw new Error("the length of name should less than 50 characters"); + throw new Error('the length of name should less than 50 characters') } if (introduction && introduction.length > 160) { throw new Error( - "the length of introduction should less than 160 characters" - ); + 'the length of introduction should less than 160 characters' + ) } if (account) { const userByAccount = await User.findOne({ where: { account }, raw: true, - nest: true, - }); + nest: true + }) if (userByAccount && userByAccount.account === account) { - throw new Error("account 已重複註冊!"); + throw new Error('account 已重複註冊!') } } if (email) { - const userByEmail = await User.findOne({ where: { email } }); + const userByEmail = await User.findOne({ where: { email } }) if (userByEmail && userByEmail.email === email) { - throw new Error("email 已重複註冊!"); + throw new Error('email 已重複註冊!') } } - const { files } = req; + const { files } = req - let newAvatar = ""; - let newCover = ""; + let newAvatar = '' + let newCover = '' - if (files && files.avatar && files.avatar[0].fieldname === "avatar") { - newAvatar = await imgurFileHandler(files.avatar[0]); + if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { + newAvatar = await imgurFileHandler(files.avatar[0]) } - if (files && files.cover && files.cover[0].fieldname === "cover") { - newCover = await imgurFileHandler(files.cover[0]); + if (files && files.cover && files.cover[0].fieldname === 'cover') { + newCover = await imgurFileHandler(files.cover[0]) } await user.update({ @@ -246,22 +246,22 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover, - }); + cover: newCover || user.cover + }) res.status(200).json({ - status: "success", - message: "Successfully update user.", - data: user, - }); + status: 'success', + message: 'Successfully update user.', + data: user + }) } catch (err) { - next(err); + next(err) } }, getUserLikes: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') // const likeTweets = await Like.findAll({ // where: { userId: id }, @@ -292,67 +292,67 @@ const userController = { // }); const likedTweets = await Tweet.findAll({ where: { userId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: User, - as: "author", - attributes: { exclude: ["password"] }, + as: 'author', + attributes: { exclude: ['password'] } }, { - model: Like, + model: Like }, { model: Reply, - as: "replies", - }, - ], - }); + as: 'replies' + } + ] + }) if (likedTweets.length === 0) { - throw new Error("the user did not like any tweet"); + throw new Error('the user did not like any tweet') } - console.log(likedTweets); - // const likedTweetsData = likeTweets.map((tweet) => ({ - // TweetId: tweet.likedTweet.id, - // tweetBelongerName: tweet.likedTweet.author.name, - // tweetBelongerAccount: tweet.likedTweet.author.account, - // tweetBelongerAvatar: tweet.likedTweet.author.avatar, - // tweetContent: tweet.likedTweet.description, - // createdAt: tweet.createdAt, - // replyCount: tweet.likedTweet.Likes.length, - // likeCount: tweet.likedTweet.replies.length, - // })); - res.status(200).json(likedTweets); + console.log(likedTweets) + const likedTweetsData = likedTweets.map(tweet => ({ + TweetId: tweet.id, + tweetBelongerName: tweet.author.name, + tweetBelongerAccount: tweet.author.account, + tweetBelongerAvatar: tweet.author.avatar, + tweetContent: tweet.description, + createdAt: tweet.createdAt, + replyCount: tweet.Likes.length, + likeCount: tweet.replies.length + })) + res.status(200).json(likedTweetsData) } catch (err) { - next(err); + next(err) } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const userTweets = await Tweet.findAll({ where: { userId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: User, - as: "author", - attributes: { exclude: ["password"] }, + as: 'author', + attributes: { exclude: ['password'] } }, { - model: Like, + model: Like }, { model: Reply, - as: "replies", - }, - ], - }); - console.log(userTweets); - const userTweetsData = userTweets.map((tweet) => ({ + as: 'replies' + } + ] + }) + console.log(userTweets) + const userTweetsData = userTweets.map(tweet => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -360,100 +360,100 @@ const userController = { description: tweet.description, createdAt: tweet.createdAt, replyCount: tweet.Likes.length, - likeCount: tweet.replies.length, - })); + likeCount: tweet.replies.length + })) - res.status(200).json(userTweetsData); + res.status(200).json(userTweetsData) } catch (err) { - next(err); + next(err) } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id const followers = await Followship.findAll({ where: { followingId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: User, - as: "follower", - attributes: { exclude: ["password"] }, - }, + as: 'follower', + attributes: { exclude: ['password'] } + } ], attributes: [ - "followerId", - "followingId", - "createdAt", - "updatedAt", + 'followerId', + 'followingId', + 'createdAt', + 'updatedAt', [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - "isFollowed", - ], + 'isFollowed' + ] ], raw: true, - nest: true, - }); - const followersData = followers.map((item) => ({ + nest: true + }) + const followersData = followers.map(item => ({ ...item, - isFollowed: item.isFollowed === 1, - })); + isFollowed: item.isFollowed === 1 + })) - res.status(200).json(followersData); + res.status(200).json(followersData) } catch (err) { - next(err); + next(err) } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); - const currentUserId = helpers.getUser(req).id; + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') + const currentUserId = helpers.getUser(req).id const following = await Followship.findAll({ where: { followerId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], include: [ { model: User, - as: "following", - attributes: { exclude: ["password"] }, - }, + as: 'following', + attributes: { exclude: ['password'] } + } ], attributes: [ - "followerId", - "followingId", - "createdAt", - "updatedAt", + 'followerId', + 'followingId', + 'createdAt', + 'updatedAt', [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` ), - "isFollowed", - ], + 'isFollowed' + ] ], raw: true, - nest: true, - }); + nest: true + }) - const followings = following.map((item) => ({ + const followings = following.map(item => ({ ...item, - isFollowed: item.isFollowed === 1, - })); - console.log(followings); - res.status(200).json(followings); + isFollowed: item.isFollowed === 1 + })) + console.log(followings) + res.status(200).json(followings) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = userController; +module.exports = userController diff --git a/middleware/error-handler.js b/middleware/error-handler.js index edcd1ee3b7..8b05e9d1b4 100644 --- a/middleware/error-handler.js +++ b/middleware/error-handler.js @@ -1,24 +1,24 @@ module.exports = { - apiErrorHandler(err, req, res, next) { + apiErrorHandler (err, req, res, next) { if (err instanceof Error) { - if (err.message === "帳號不存在") { + if (err.message === '帳號不存在') { return res.status(200).json({ - status: "error", - statusCode: "404", - message: `${err.message}`, - }); + status: 'error', + statusCode: '404', + message: `${err.message}` + }) } res.status(200).json({ - status: "error", - statusCode: "400", - message: `${err.message}`, - }); + status: 'error', + statusCode: '400', + message: `${err.message}` + }) } else { res.status(500).json({ - status: "error", - message: `${err}`, - }); + status: 'error', + message: `${err}` + }) } - next(err); - }, -}; + next(err) + } +} From 58335ceeefddd82868db4c61f00ed9b12a1277bb Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Wed, 30 Aug 2023 23:16:15 +0800 Subject: [PATCH 119/170] fix: getTweets and getTweet --- controllers/apis/tweet-controller.js | 33 ++++++++++++---------- seeders/20230821074916-tweets-seed-file.js | 4 +-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index 9a94aa69c9..a52b9dc7ee 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -20,8 +20,7 @@ const tweetContorller = { { model: User, attributes: ['id', 'account', 'name', 'avatar'], - as: 'author', - where: { role: 'user' } + as: 'author' }, { model: Like @@ -33,20 +32,23 @@ const tweetContorller = { ] } const tweets = await Tweet.findAll(options) - console.log(tweets) + + if (!tweets) throw new Error("Tweet didn't exist!") const dataTweets = tweets.map(tweet => ({ - id: tweet.id, + UserId: tweet.userId, + TweetId: tweet.id, authorId: tweet.author.id, authorAccount: tweet.author.account, authorName: tweet.author.name, authorAvatar: tweet.author.avatar, - description: tweet.description.substring(0, 140), + description: tweet.description, likeCount: tweet.Likes.length, replyCount: tweet.replies.length, isLiked: tweet.Likes.some(i => i.userId === userId), createdAt: tweet.createdAt })) + res.status(200).json(dataTweets) } catch (err) { next(err) @@ -76,19 +78,20 @@ const tweetContorller = { }) if (!tweet) throw new Error("Tweet didn't exist!") - console.log(tweet) - const tweetData = [tweet].map(t => ({ - id: t.id, - authorName: t.author.name, - authorAccount: t.author.account, - authorAvatar: t.author.avatar, - description: t.description, + const tweetData = { + id: tweet.id, + authorId: tweet.author.id, + authorAccount: tweet.author.account, + authorName: tweet.author.name, + authorAvatar: tweet.author.avatar, + description: tweet.description.substring(0, 140), likeCount: tweet.Likes.length, replyCount: tweet.replies.length, - isLiked: t.Likes.some(i => i.userId === userId), - createdAt: t.createdAt - })) + isLiked: tweet.Likes.some(i => i.userId === userId), + createdAt: tweet.createdAt + } + res.status(200).json(tweetData) } catch (err) { next(err) diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index f0390b6fdb..8985cf2133 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -17,8 +17,8 @@ module.exports = { description: faker.lorem.text(140), created_at: new Date(), updated_at: new Date(), - like_count: faker.random.number(), - reply_count: faker.random.number(), + like_count: faker.datatype.number(), + reply_count: faker.datatype.number(), User_id: userData[i].id }) } From 509fdf62346590901b0cb169d64e90792a8b6033 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Wed, 30 Aug 2023 23:29:12 +0800 Subject: [PATCH 120/170] fix: remove name required option --- controllers/apis/user-controller.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 6aabab2d29..8125f47e3c 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -14,8 +14,8 @@ const userController = { try { const { account, name, email, password, checkPassword } = req.body - if (!account || !name || !email || !password || !checkPassword) { - throw new Error('all the blanks are required') + if (!account || !email || !password || !checkPassword) { + throw new Error('Please enter account, email, password and checkPassword') } // 檢查帳號是否重複 @@ -31,7 +31,7 @@ const userController = { } const createdUser = await User.create({ - name, + name: name || account, email, account, password: bcrypt.hashSync(password, 10), From 20e9e0a226006bfe31171bc382e2894e3dbe4588 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 00:13:49 +0800 Subject: [PATCH 121/170] fix: follow user 500 err --- controllers/apis/followship-controller.js | 23 ++++++++++--------- controllers/apis/user-controller.js | 27 ----------------------- 2 files changed, 13 insertions(+), 37 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 3fe71c18d3..e2c902199f 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -9,18 +9,21 @@ const followshipController = { const followingId = req.body.id const getUser = helpers.getUser(req) const userId = getUser.id - const [user, followship] = await Promise.all([ - User.findByPk(userId), - Followship.findOne({ - where: { followerId: userId, followingId } - }) - ]) + const user = await User.findByPk(userId) if (!user) throw new Error("User didn't exist!") - if (followship) throw new Error("You've are already followed this user!") - Followship.create({ - followerId: userId, - followingId + const followship = await Followship.findOrCreate({ + raw: true, + nest: true, + where: { + followerId: userId, + followingId + } }) + + if (!followship[1]) { + throw new Error("You've are already followed this user!") + } + console.log(followship) res.status(200).json({ status: 'success', message: 'successfully follow user!' diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index b569141dd6..d7dfb762b2 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -263,33 +263,6 @@ const userController = { const user = await User.findByPk(id, { raw: true, nest: true }) if (!user) throw new Error('User does not exist') - // const likeTweets = await Like.findAll({ - // where: { userId: id }, - // order: [["createdAt", "DESC"]], - // include: [ - // { - // model: Tweet, - // as: "likedTweet", - // raw: true, - // nest: true, - // attributes: { exclude: ["password"] }, - // include: [ - // { - // model: User, - // as: "author", - // attributes: ["account", "name", "avatar"], - // }, - // { - // model: Like, - // }, - // { - // model: Reply, - // as: "replies", - // }, - // ], - // }, - // ], - // }); const likedTweets = await Tweet.findAll({ where: { userId: id }, order: [['createdAt', 'DESC']], From d468eb2ec997e87663aa6659c499865efc913b8f Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 13:30:44 +0800 Subject: [PATCH 122/170] fix: followship/unfollow --- controllers/apis/followship-controller.js | 19 +++++++++--------- controllers/apis/user-controller.js | 6 ++++-- middleware/error-handler.js | 24 +++++++++++++---------- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index e2c902199f..6cc3b3b9ec 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -37,17 +37,18 @@ const followshipController = { const followingId = req.params.following_id const getUser = helpers.getUser(req) const userId = getUser.id - const [user, followship] = await Promise.all([ - User.findByPk(userId), - Followship.findOne({ - where: { followerId: userId, followingId } - }) - ]) + const user = await User.findByPk(userId) if (!user) throw new Error("User didn't exist!") - if (!followship) throw new Error("You haven't followed this user!") - Followship.destroy({ - where: { followerId: userId, followingId } + const followship = await Followship.destroy({ + where: { + followerId: userId, + followingId + } }) + + if (!followship[1]) { + throw new Error("You've are already followed this user!") + } res.status(200).json({ status: 'success', message: 'successfully unfollow user!' diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index d7dfb762b2..66db65d4fd 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -15,7 +15,9 @@ const userController = { const { account, name, email, password, checkPassword } = req.body if (!account || !email || !password || !checkPassword) { - throw new Error('Please enter account, email, password and checkPassword') + throw new Error( + 'Please enter account, email, password and checkPassword' + ) } // 檢查帳號是否重複 @@ -416,7 +418,7 @@ const userController = { raw: true, nest: true }) - + console.log(following) const followings = following.map(item => ({ ...item, isFollowed: item.isFollowed === 1 diff --git a/middleware/error-handler.js b/middleware/error-handler.js index 8b05e9d1b4..7014320dd0 100644 --- a/middleware/error-handler.js +++ b/middleware/error-handler.js @@ -1,18 +1,22 @@ module.exports = { apiErrorHandler (err, req, res, next) { if (err instanceof Error) { - if (err.message === '帳號不存在') { - return res.status(200).json({ - status: 'error', - statusCode: '404', - message: `${err.message}` - }) - } - res.status(200).json({ + res.status(err.status || 500).json({ status: 'error', - statusCode: '400', - message: `${err.message}` + message: `${err.name}: ${err.message}` }) + // if (err.message === "帳號不存在") { + // return res.status(200).json({ + // status: "error", + // statusCode: "404", + // message: `${err.message}`, + // }); + // } + // res.status(200).json({ + // status: "error", + // statusCode: "400", + // message: `${err.message}`, + // }); } else { res.status(500).json({ status: 'error', From ac17538281dfdbaa52fae4979c8fb4a79a400b10 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 14:12:38 +0800 Subject: [PATCH 123/170] fix: top 10 --- controllers/apis/followship-controller.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 6cc3b3b9ec..eaafe6dff0 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -100,9 +100,12 @@ const followshipController = { raw: true, nest: true }) - + const top10 = top10UsersWithFollowStatus.map(item => ({ + ...item, + isFollowed: item.isFollowed === 1 + })) res.status(200).json({ - top10UsersWithFollowStatus + top10 }) } catch (err) { next(err) From bc82b6af49bcb76cdb3e9f30d9f9f9fe56066ea3 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 14:14:59 +0800 Subject: [PATCH 124/170] fix: bugs --- controllers/apis/followship-controller.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index eaafe6dff0..ab625a18b2 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -63,7 +63,7 @@ const followshipController = { const currentUserId = getUser.id if (!currentUserId) throw new Error("User didn't exist!") - const top10UsersWithFollowStatus = await User.findAll({ + const top10 = await User.findAll({ where: { role: 'user', id: { [sequelize.Op.not]: currentUserId } @@ -100,12 +100,14 @@ const followshipController = { raw: true, nest: true }) - const top10 = top10UsersWithFollowStatus.map(item => ({ + const top10UsersWithFollowStatus + top10UsersWithFollowStatus = top10.map(item => ({ ...item, isFollowed: item.isFollowed === 1 })) res.status(200).json({ - top10 + top10UsersWithFollowStatus +top10UsersWithFollowStatus }) } catch (err) { next(err) From 7fa472cd38c6a9a7c2205f26c3b277349ccb0175 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 14:15:29 +0800 Subject: [PATCH 125/170] fix: bugs --- controllers/apis/followship-controller.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index ab625a18b2..623ac758d3 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -100,14 +100,12 @@ const followshipController = { raw: true, nest: true }) - const top10UsersWithFollowStatus - top10UsersWithFollowStatus = top10.map(item => ({ + const top10UsersWithFollowStatus = top10.map(item => ({ ...item, isFollowed: item.isFollowed === 1 })) res.status(200).json({ top10UsersWithFollowStatus -top10UsersWithFollowStatus }) } catch (err) { next(err) From 29b319a97a14c6c02c5452b42325c290af469bef Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 14:39:27 +0800 Subject: [PATCH 126/170] fix:top 10 bugs --- controllers/apis/followship-controller.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 623ac758d3..9ff78fcf9c 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -100,10 +100,14 @@ const followshipController = { raw: true, nest: true }) - const top10UsersWithFollowStatus = top10.map(item => ({ - ...item, - isFollowed: item.isFollowed === 1 - })) + + const top10UsersWithFollowStatus = [] + top10.forEach(item => { + top10UsersWithFollowStatus.push({ + ...item, + isFollowed: item.isFollowed === 1 + }) + }) res.status(200).json({ top10UsersWithFollowStatus }) From b31019b11ae693f83c044d657760950c373aad1f Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 16:04:32 +0800 Subject: [PATCH 127/170] fix : created at timezone --- controllers/apis/followship-controller.js | 6 +++--- controllers/apis/tweet-controller.js | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 9ff78fcf9c..32671e3b75 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -34,9 +34,9 @@ const followshipController = { }, unfollowUser: async (req, res, next) => { try { - const followingId = req.params.following_id + const followingId = req.params.following_id // 我要取消追蹤的對象 const getUser = helpers.getUser(req) - const userId = getUser.id + const userId = getUser.id // 現在使用者本人 const user = await User.findByPk(userId) if (!user) throw new Error("User didn't exist!") const followship = await Followship.destroy({ @@ -47,7 +47,7 @@ const followshipController = { }) if (!followship[1]) { - throw new Error("You've are already followed this user!") + throw new Error("You haven't followed this user!") } res.status(200).json({ status: 'success', diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index a52b9dc7ee..ea869b1f2a 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -164,11 +164,12 @@ const tweetContorller = { const userId = getUser.id if (!description) throw new Error('文章內容不可為空白') if (description.length > 140) throw new Error('文章內容不可超過 140 字') + const createdTweet = await Tweet.create({ userId, - description, - createdAt: new Date(), - updatedAt: new Date() + description + // createdAt: date, + // updatedAt: date, }) res.status(200).json({ status: 'success', From b9c3e0eee19b8897cdb2a9b58f1499e1b507c46e Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 17:02:01 +0800 Subject: [PATCH 128/170] fix: seeder reply text --- seeders/20230821081029-replies-seed-file.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seeders/20230821081029-replies-seed-file.js b/seeders/20230821081029-replies-seed-file.js index 93ba3e42ee..5b881b8cdb 100644 --- a/seeders/20230821081029-replies-seed-file.js +++ b/seeders/20230821081029-replies-seed-file.js @@ -22,7 +22,7 @@ module.exports = { const tweet = { Tweet_id: tweetData[Math.floor(i / 3)].id, User_id: userData[Math.floor(Math.random() * userData.length)].id, - comment: faker.lorem.text(), + comment: faker.lorem.text(20), created_at: new Date(), updated_at: new Date() } From c221cf5bf31d9f7c6f595322b56dd88fa6abfc0e Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 20:22:35 +0800 Subject: [PATCH 129/170] fix: like count and reply count --- controllers/apis/user-controller.js | 87 +++++++++++++++-------------- routes/index.js | 7 +-- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 66db65d4fd..dc7f5817cf 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -132,7 +132,7 @@ const userController = { next(err) } }, - getUserReplies: async (req, res, next) => { + getUserRepliedTweets: async (req, res, next) => { try { const userId = req.params.id @@ -156,6 +156,9 @@ const userController = { ], order: [['createdAt', 'DESC']], nest: true + }), + Like.findAll({ + where: { userId } }) ]) @@ -265,24 +268,25 @@ const userController = { const user = await User.findByPk(id, { raw: true, nest: true }) if (!user) throw new Error('User does not exist') - const likedTweets = await Tweet.findAll({ - where: { userId: id }, - order: [['createdAt', 'DESC']], - include: [ - { - model: User, - as: 'author', - attributes: { exclude: ['password'] } - }, - { - model: Like - }, - { - model: Reply, - as: 'replies' - } - ] - }) + const [likedTweets, likeCount, replyCount] = await Promise.all([ + Tweet.findAll({ + where: { userId: id }, + order: [['createdAt', 'DESC']], + include: [ + { + model: User, + as: 'author', + attributes: { exclude: ['password'] } + } + ] + }), + Like.findAll({ + where: { userId: id } + }), + Reply.findAll({ + where: { userId: id } + }) + ]) if (likedTweets.length === 0) { throw new Error('the user did not like any tweet') } @@ -294,8 +298,8 @@ const userController = { tweetBelongerAvatar: tweet.author.avatar, tweetContent: tweet.description, createdAt: tweet.createdAt, - replyCount: tweet.Likes.length, - likeCount: tweet.replies.length + replyCount: replyCount.length, + likeCount: likeCount.length })) res.status(200).json(likedTweetsData) } catch (err) { @@ -308,24 +312,25 @@ const userController = { const user = await User.findByPk(id, { raw: true, nest: true }) if (!user) throw new Error('User does not exist') - const userTweets = await Tweet.findAll({ - where: { userId: id }, - order: [['createdAt', 'DESC']], - include: [ - { - model: User, - as: 'author', - attributes: { exclude: ['password'] } - }, - { - model: Like - }, - { - model: Reply, - as: 'replies' - } - ] - }) + const [userTweets, likeCount, replyCount] = await Promise.all([ + Tweet.findAll({ + where: { userId: id }, + order: [['createdAt', 'DESC']], + include: [ + { + model: User, + as: 'author', + attributes: { exclude: ['password'] } + } + ] + }), + Like.findAll({ + where: { userId: id } + }), + Reply.findAll({ + where: { userId: id } + }) + ]) console.log(userTweets) const userTweetsData = userTweets.map(tweet => ({ TweetId: tweet.id, @@ -334,8 +339,8 @@ const userController = { tweetBelongerAvatar: tweet.author.avatar, description: tweet.description, createdAt: tweet.createdAt, - replyCount: tweet.Likes.length, - likeCount: tweet.replies.length + replyCount: replyCount.length, + likeCount: likeCount.length })) res.status(200).json(userTweetsData) diff --git a/routes/index.js b/routes/index.js index dfd2913283..6d9a2dd1c6 100644 --- a/routes/index.js +++ b/routes/index.js @@ -8,10 +8,7 @@ const followshipController = require('../controllers/apis/followship-controller' const { apiErrorHandler } = require('../middleware/error-handler') -const { - authenticated, - authenticatedUser -} = require('../middleware/api-auth') +const { authenticated, authenticatedUser } = require('../middleware/api-auth') // api/admin router.use('/api/admin', admin) @@ -57,7 +54,7 @@ router.get( '/api/users/:id/replied_tweets', authenticated, authenticatedUser, - userController.getUserReplies + userController.getUserRepliedTweets ) router.get( '/api/users/:id', From 83789d0eca458020cbdd89412dda276854a7b747 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 21:29:12 +0800 Subject: [PATCH 130/170] fix: reply count like count --- controllers/apis/user-controller.js | 35 ++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index dc7f5817cf..c0fa941a01 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -311,11 +311,32 @@ const userController = { const { id } = req.params const user = await User.findByPk(id, { raw: true, nest: true }) if (!user) throw new Error('User does not exist') - - const [userTweets, likeCount, replyCount] = await Promise.all([ + const [userTweets] = await Promise.all([ Tweet.findAll({ where: { userId: id }, order: [['createdAt', 'DESC']], + attributes: [ + 'id', + 'description', + 'createdAt', + 'updatedAt', + [ + sequelize.literal(`( + SELECT COUNT(*) + FROM Likes + WHERE Likes.tweet_id = tweet.id + )`), + 'likeCount' + ], + [ + sequelize.literal(`( + SELECT COUNT(*) + FROM Replies + WHERE Replies.tweet_id = tweet.id + )`), + 'replyCount' + ] + ], include: [ { model: User, @@ -323,12 +344,6 @@ const userController = { attributes: { exclude: ['password'] } } ] - }), - Like.findAll({ - where: { userId: id } - }), - Reply.findAll({ - where: { userId: id } }) ]) console.log(userTweets) @@ -339,8 +354,8 @@ const userController = { tweetBelongerAvatar: tweet.author.avatar, description: tweet.description, createdAt: tweet.createdAt, - replyCount: replyCount.length, - likeCount: likeCount.length + replyCount: 999, + likeCount: 999 })) res.status(200).json(userTweetsData) From 5a56ac3b8111e84cb728ece2e5b4469fb1fec30d Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 21:30:36 +0800 Subject: [PATCH 131/170] fix: bugs --- controllers/apis/user-controller.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index c0fa941a01..e3745d884d 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -353,9 +353,7 @@ const userController = { tweetBelongerAccount: tweet.author.account, tweetBelongerAvatar: tweet.author.avatar, description: tweet.description, - createdAt: tweet.createdAt, - replyCount: 999, - likeCount: 999 + createdAt: tweet.createdAt })) res.status(200).json(userTweetsData) From 4973ca5e15e6cf6c37cedfd3a01f1bc2f502998e Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 21:34:20 +0800 Subject: [PATCH 132/170] fix: bugs --- controllers/apis/user-controller.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index e3745d884d..ada146212f 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -353,7 +353,9 @@ const userController = { tweetBelongerAccount: tweet.author.account, tweetBelongerAvatar: tweet.author.avatar, description: tweet.description, - createdAt: tweet.createdAt + createdAt: tweet.createdAt, + replyCount: tweet.replyCount, + likeCount: tweet.likeCount })) res.status(200).json(userTweetsData) From ce3c17f644f6854123c1b5a3f0ef2861ae338ade Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 21:41:18 +0800 Subject: [PATCH 133/170] fix: bugs --- controllers/apis/user-controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index ada146212f..6309ad95cc 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -324,7 +324,7 @@ const userController = { sequelize.literal(`( SELECT COUNT(*) FROM Likes - WHERE Likes.tweet_id = tweet.id + WHERE Likes.tweet_id = Tweet.id )`), 'likeCount' ], @@ -332,7 +332,7 @@ const userController = { sequelize.literal(`( SELECT COUNT(*) FROM Replies - WHERE Replies.tweet_id = tweet.id + WHERE Replies.tweet_id = Tweet.id )`), 'replyCount' ] From f292f60501413d84dc1c65b4159961e041d8dffd Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 31 Aug 2023 21:56:49 +0800 Subject: [PATCH 134/170] fix: getFollowers and getFollowings and isFollowed --- controllers/apis/user-controller.js | 102 ++++++++++++---------------- 1 file changed, 43 insertions(+), 59 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index b569141dd6..9835ee3923 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -370,40 +370,33 @@ const userController = { }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) + const { id } = req.params // 18 target + const user = await User.findByPk(id, { + include: { + model: User, + as: 'Followers' + } + } + ) + if (!user) throw new Error('User does not exist') + if (!user.Followers) return res.status(200).json({ status: 'success', message: 'No followers' }) const currentUserId = helpers.getUser(req).id - const followers = await Followship.findAll({ - where: { followingId: id }, - order: [['createdAt', 'DESC']], - include: [ - { - model: User, - as: 'follower', - attributes: { exclude: ['password'] } - } - ], - attributes: [ - 'followerId', - 'followingId', - 'createdAt', - 'updatedAt', - [ - sequelize.literal( - `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` - ), - 'isFollowed' - ] - ], - raw: true, - nest: true + const currentUserFollowingId = await Followship.findAll({ + where: { followerId: currentUserId }, + raw: true }) - const followersData = followers.map(item => ({ - ...item, - isFollowed: item.isFollowed === 1 + + const followingIds = currentUserFollowingId.map(item => item.followingId) + + const followersData = user.Followers.map(follower => ({ + followerId: follower.id, + followerAccount: follower.account, + followerName: follower.name, + followerAvatar: follower.avatar, + isFollowed: followingIds.includes(follower.id) })) res.status(200).json(followersData) @@ -414,42 +407,33 @@ const userController = { getUserFollowings: async (req, res, next) => { try { const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) + const user = await User.findByPk(id, { + include: { + model: User, + as: 'Followings' + } + }) if (!user) throw new Error('User does not exist') + if (!user.Followings) return res.status(200).json({ status: 'success', message: 'No followings' }) + const currentUserId = helpers.getUser(req).id - const following = await Followship.findAll({ - where: { followerId: id }, - order: [['createdAt', 'DESC']], - include: [ - { - model: User, - as: 'following', - attributes: { exclude: ['password'] } - } - ], - attributes: [ - 'followerId', - 'followingId', - 'createdAt', - 'updatedAt', - [ - sequelize.literal( - `(CASE WHEN EXISTS (SELECT 1 FROM Followships WHERE follower_id = ${currentUserId} AND following_id = ${id}) THEN TRUE ELSE FALSE END)` - ), - 'isFollowed' - ] - ], - raw: true, - nest: true + const currentUserFollowingId = await Followship.findAll({ + where: { followerId: currentUserId }, + raw: true }) - const followings = following.map(item => ({ - ...item, - isFollowed: item.isFollowed === 1 + const followingIds = currentUserFollowingId.map(item => item.followingId) + + const followingsData = user.Followings.map(following => ({ + followingId: following.id, + followingAccount: following.account, + followingName: following.name, + followingAvatar: following.avatar, + isFollowed: followingIds.includes(following.id) })) - console.log(followings) - res.status(200).json(followings) + + res.status(200).json(followingsData) } catch (err) { next(err) } From c3f0f5529c4e33f6d6f818ca88c95d5b873e3e64 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 22:55:26 +0800 Subject: [PATCH 135/170] fix: user cover img --- seeders/20230821044414-users-seed-file.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/seeders/20230821044414-users-seed-file.js b/seeders/20230821044414-users-seed-file.js index ffdc9d3b13..c1fee92b62 100644 --- a/seeders/20230821044414-users-seed-file.js +++ b/seeders/20230821044414-users-seed-file.js @@ -16,7 +16,7 @@ module.exports = { avatar: `https://loremflickr.com/150/150/boy/?random=${ Math.random() * 100 }`, - cover: `https://loremflickr.com/300/200/city/?random=${ + cover: `https://loremflickr.com/1480/480/city/?random=${ Math.random() * 100 }`, introduction: faker.lorem.text().substring(0, 160), @@ -33,7 +33,7 @@ module.exports = { role: 'user', name: `User${i}`, account: `user${i}`, - avatar: `https://loremflickr.com/320/240/man/?random=${ + avatar: `https://loremflickr.com/150/150/boy/?random=${ Math.random() * 100 }`, cover: `https://loremflickr.com/1440/480/city/?random=${ From 35639d58d5f545d069b7767cad4f1f919c5fe2fd Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Thu, 31 Aug 2023 23:34:54 +0800 Subject: [PATCH 136/170] fix: revise data structure --- controllers/apis/user-controller.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 8ca4dd2daa..5fdeffef6b 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -287,9 +287,8 @@ const userController = { where: { userId: id } }) ]) - if (likedTweets.length === 0) { - throw new Error('the user did not like any tweet') - } + if (likedTweets.length === 0) return res.status(200).json({ status: 'success', message: 'No likes' }) + console.log(likedTweets) const likedTweetsData = likedTweets.map(tweet => ({ TweetId: tweet.id, @@ -391,7 +390,8 @@ const userController = { followerAccount: follower.account, followerName: follower.name, followerAvatar: follower.avatar, - isFollowed: followingIds.includes(follower.id) + isFollowed: followingIds.includes(follower.id), + follower })) res.status(200).json(followersData) @@ -425,7 +425,8 @@ const userController = { followingAccount: following.account, followingName: following.name, followingAvatar: following.avatar, - isFollowed: followingIds.includes(following.id) + isFollowed: followingIds.includes(following.id), + following })) res.status(200).json(followingsData) From 760f3ca3e46c426ce5b2fa91bb94f278aa5af87d Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Thu, 31 Aug 2023 23:35:11 +0800 Subject: [PATCH 137/170] fix : bugs --- controllers/apis/followship-controller.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 32671e3b75..fc5bee3ba4 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -19,7 +19,9 @@ const followshipController = { followingId } }) - + // const Newfollowship = followship[0].followingId; + // console.log(Newfollowship); + // console.log(followship); if (!followship[1]) { throw new Error("You've are already followed this user!") } @@ -46,7 +48,7 @@ const followshipController = { } }) - if (!followship[1]) { + if (followship[1]) { throw new Error("You haven't followed this user!") } res.status(200).json({ From 9b88b198d59f3efad0986a57c17523e26a23fa1d Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 1 Sep 2023 10:23:37 +0800 Subject: [PATCH 138/170] fix: getUser liked tweets --- controllers/apis/user-controller.js | 114 ++++++++++++++++++---------- 1 file changed, 76 insertions(+), 38 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 5fdeffef6b..01a9c96651 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -8,6 +8,7 @@ const helpers = require('../../_helpers') const { User, Tweet, Reply, Followship, Like } = db const { Op } = require('sequelize') +const like = require('../../models/like') const userController = { signUp: async (req, res, next) => { @@ -267,38 +268,64 @@ const userController = { const { id } = req.params const user = await User.findByPk(id, { raw: true, nest: true }) if (!user) throw new Error('User does not exist') - - const [likedTweets, likeCount, replyCount] = await Promise.all([ - Tweet.findAll({ - where: { userId: id }, - order: [['createdAt', 'DESC']], - include: [ - { - model: User, - as: 'author', - attributes: { exclude: ['password'] } - } - ] - }), - Like.findAll({ - where: { userId: id } - }), - Reply.findAll({ - where: { userId: id } - }) - ]) - if (likedTweets.length === 0) return res.status(200).json({ status: 'success', message: 'No likes' }) - - console.log(likedTweets) - const likedTweetsData = likedTweets.map(tweet => ({ - TweetId: tweet.id, - tweetBelongerName: tweet.author.name, - tweetBelongerAccount: tweet.author.account, - tweetBelongerAvatar: tweet.author.avatar, - tweetContent: tweet.description, - createdAt: tweet.createdAt, - replyCount: replyCount.length, - likeCount: likeCount.length + const likes = await Like.findAll({ + where: { userId: id }, + raw: true, + nest: true, + include: [ + // { + // model: User, + // attributes: { exclude: ["password"] }, + // }, + { + model: Tweet, + as: 'likedTweet', + attributes: [ + 'id', + 'UserId', + 'description', + 'createdAt', + 'updatedAt', + [ + sequelize.literal( + '(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)' + ), + 'replyCount' + ], + [ + sequelize.literal( + '(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)' + ), + 'likeCount' + ], + [ + sequelize.literal( + `(CASE WHEN EXISTS (SELECT 1 FROM Likes WHERE tweet_id = likedTweet.id AND user_id = ${id}) THEN TRUE ELSE FALSE END)` + ), + 'isLiked' + ] + ], + include: [ + { model: User, as: 'author' } + // { model: Reply, as: "replies" }, + ] + } + ] + }) + console.log(likes) + + if (likes.length === 0) { return res.status(200).json({ status: 'success', message: 'No likes' }) } + + const likedTweetsData = likes.map(like => ({ + TweetId: like.likedTweet.id, + tweetBelongerName: like.likedTweet.author.name, + tweetBelongerAccount: like.likedTweet.author.account, + tweetBelongerAvatar: like.likedTweet.author.avatar, + tweetContent: like.likedTweet.description, + createdAt: like.likedTweet.createdAt, + replyCount: like.likedTweet.replyCount, + likeCount: like.likedTweet.likeCount, + isLiked: like.likedTweet.isLiked })) res.status(200).json(likedTweetsData) } catch (err) { @@ -370,11 +397,14 @@ const userController = { model: User, as: 'Followers' } - } - ) + }) if (!user) throw new Error('User does not exist') - if (!user.Followers) return res.status(200).json({ status: 'success', message: 'No followers' }) + if (!user.Followers) { + return res + .status(200) + .json({ status: 'success', message: 'No followers' }) + } const currentUserId = helpers.getUser(req).id @@ -383,7 +413,9 @@ const userController = { raw: true }) - const followingIds = currentUserFollowingId.map(item => item.followingId) + const followingIds = currentUserFollowingId.map( + item => item.followingId + ) const followersData = user.Followers.map(follower => ({ followerId: follower.id, @@ -409,7 +441,11 @@ const userController = { } }) if (!user) throw new Error('User does not exist') - if (!user.Followings) return res.status(200).json({ status: 'success', message: 'No followings' }) + if (!user.Followings) { + return res + .status(200) + .json({ status: 'success', message: 'No followings' }) + } const currentUserId = helpers.getUser(req).id @@ -418,7 +454,9 @@ const userController = { raw: true }) - const followingIds = currentUserFollowingId.map(item => item.followingId) + const followingIds = currentUserFollowingId.map( + item => item.followingId + ) const followingsData = user.Followings.map(following => ({ followingId: following.id, From d91390f581911f5e0dd44a2f70fdcfa4aca4e0e1 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 1 Sep 2023 10:29:01 +0800 Subject: [PATCH 139/170] fix: bugs --- controllers/apis/user-controller.js | 395 ++++++++++++++-------------- 1 file changed, 199 insertions(+), 196 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 01a9c96651..fc3cd1602a 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,36 +1,36 @@ -const bcrypt = require('bcryptjs') -const jwt = require('jsonwebtoken') -const sequelize = require('sequelize') -const { imgurFileHandler } = require('../../helpers/file-helpers') +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken"); +const sequelize = require("sequelize"); +const { imgurFileHandler } = require("../../helpers/file-helpers"); -const db = require('../../models') -const helpers = require('../../_helpers') +const db = require("../../models"); +const helpers = require("../../_helpers"); -const { User, Tweet, Reply, Followship, Like } = db -const { Op } = require('sequelize') -const like = require('../../models/like') +const { User, Tweet, Reply, Followship, Like } = db; +const { Op } = require("sequelize"); +const like = require("../../models/like"); const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body + const { account, name, email, password, checkPassword } = req.body; if (!account || !email || !password || !checkPassword) { throw new Error( - 'Please enter account, email, password and checkPassword' - ) + "Please enter account, email, password and checkPassword" + ); } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }] - } - }) + [Op.or]: [{ email }, { account }], + }, + }); if (user) { - if (user.account === account) throw new Error('account 已重複註冊!') - if (user.email === email) throw new Error('email 已重複註冊!') + if (user.account === account) throw new Error("account 已重複註冊!"); + if (user.email === email) throw new Error("email 已重複註冊!"); } const createdUser = await User.create({ @@ -38,104 +38,104 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: 'https://picsum.photos/100/100', - cover: 'https://picsum.photos/id/237/700/400', - role: 'user', + avatar: "https://picsum.photos/100/100", + cover: "https://picsum.photos/id/237/700/400", + role: "user", createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create user.', - data: createdUser - }) + status: "success", + message: "Successfully create user.", + data: createdUser, + }); } catch (err) { - next(err) + next(err); } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body + const { account, password } = req.body; if (!account || !password) { - throw new Error('Please enter account and password') + throw new Error("Please enter account and password"); } - const user = await User.findOne({ where: { account } }) - if (!user) throw new Error('User does not exist') - if (user.role === 'admin') throw new Error('admin permission denied') + const user = await User.findOne({ where: { account } }); + if (!user) throw new Error("User does not exist"); + if (user.role === "admin") throw new Error("admin permission denied"); if (!bcrypt.compareSync(password, user.password)) { - throw new Error('Incorrect password') + throw new Error("Incorrect password"); } const payload = { id: user.id, account: user.account, - role: user.role - } + role: user.role, + }; const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: '30d' - }) - const userId = user.toJSON().id + expiresIn: "30d", + }); + const userId = user.toJSON().id; res.status(200).json({ - status: 'success', + status: "success", data: { token, - userId - } - }) + userId, + }, + }); } catch (err) { - next(err) + next(err); } }, getUser: async (req, res, next) => { try { - const { id } = req.params - const currentUserId = helpers.getUser(req).id + const { id } = req.params; + const currentUserId = helpers.getUser(req).id; const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id } + where: { UserId: id }, }), Followship.count({ - where: { followerId: id } + where: { followerId: id }, }), Followship.count({ - where: { followingId: id } - }) - ]) + where: { followingId: id }, + }), + ]); if (!user) { return res .status(401) - .json({ status: 'error', message: 'This user does not exist' }) + .json({ status: "error", message: "This user does not exist" }); } - delete user.password - user.tweetCount = tweetCount - user.followerCount = followerCount - user.followingCount = followingCount + delete user.password; + user.tweetCount = tweetCount; + user.followerCount = followerCount; + user.followingCount = followingCount; if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); user.isFollowed = checkUserFollowing.some( - follow => follow.followingId === Number(id) - ) + (follow) => follow.followingId === Number(id) + ); } - console.log(user) - res.status(200).json(user) + console.log(user); + res.status(200).json(user); } catch (err) { - next(err) + next(err); } }, getUserRepliedTweets: async (req, res, next) => { try { - const userId = req.params.id + const userId = req.params.id; const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -144,26 +144,26 @@ const userController = { include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ - { model: User, as: 'author', attributes: ['account', 'name'] } - ] - } + { model: User, as: "author", attributes: ["account", "name"] }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true + order: [["createdAt", "DESC"]], + nest: true, }), Like.findAll({ - where: { userId } - }) - ]) + where: { userId }, + }), + ]); - const userRepliesResult = replies.map(reply => ({ + const userRepliesResult = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: user.id, @@ -173,76 +173,76 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - res.status(200).json(userRepliesResult) + res.status(200).json(userRepliesResult); } catch (err) { - next(err) + next(err); } }, updateUser: async (req, res, next) => { try { - const { id } = req.params - const { account, name, email, password, introduction } = req.body + const { id } = req.params; + const { account, name, email, password, introduction } = req.body; - const user = await User.findByPk(id) + const user = await User.findByPk(id); if (!user) { return res.status(401).json({ - status: 'error', - message: 'This user does not exist' - }) + status: "error", + message: "This user does not exist", + }); } - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; if (!currentUserId) { - throw new Error('Current user ID is missing') + throw new Error("Current user ID is missing"); } if (currentUserId !== Number(id)) { - throw new Error('Cannot edit other users profile') + throw new Error("Cannot edit other users profile"); } if (name && name.length > 50) { - throw new Error('the length of name should less than 50 characters') + throw new Error("the length of name should less than 50 characters"); } if (introduction && introduction.length > 160) { throw new Error( - 'the length of introduction should less than 160 characters' - ) + "the length of introduction should less than 160 characters" + ); } if (account) { const userByAccount = await User.findOne({ where: { account }, raw: true, - nest: true - }) + nest: true, + }); if (userByAccount && userByAccount.account === account) { - throw new Error('account 已重複註冊!') + throw new Error("account 已重複註冊!"); } } if (email) { - const userByEmail = await User.findOne({ where: { email } }) + const userByEmail = await User.findOne({ where: { email } }); if (userByEmail && userByEmail.email === email) { - throw new Error('email 已重複註冊!') + throw new Error("email 已重複註冊!"); } } - const { files } = req + const { files } = req; - let newAvatar = '' - let newCover = '' + let newAvatar = ""; + let newCover = ""; - if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { - newAvatar = await imgurFileHandler(files.avatar[0]) + if (files && files.avatar && files.avatar[0].fieldname === "avatar") { + newAvatar = await imgurFileHandler(files.avatar[0]); } - if (files && files.cover && files.cover[0].fieldname === 'cover') { - newCover = await imgurFileHandler(files.cover[0]) + if (files && files.cover && files.cover[0].fieldname === "cover") { + newCover = await imgurFileHandler(files.cover[0]); } await user.update({ @@ -252,22 +252,23 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover - }) + cover: newCover || user.cover, + }); res.status(200).json({ - status: 'success', - message: 'Successfully update user.', - data: user - }) + status: "success", + message: "Successfully update user.", + data: user, + }); } catch (err) { - next(err) + next(err); } }, getUserLikes: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const currentUserId = helpers.getUser(req).id; + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); const likes = await Like.findAll({ where: { userId: id }, raw: true, @@ -279,44 +280,46 @@ const userController = { // }, { model: Tweet, - as: 'likedTweet', + as: "likedTweet", attributes: [ - 'id', - 'UserId', - 'description', - 'createdAt', - 'updatedAt', + "id", + "UserId", + "description", + "createdAt", + "updatedAt", [ sequelize.literal( - '(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)' + "(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)" ), - 'replyCount' + "replyCount", ], [ sequelize.literal( - '(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)' + "(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)" ), - 'likeCount' + "likeCount", ], [ sequelize.literal( - `(CASE WHEN EXISTS (SELECT 1 FROM Likes WHERE tweet_id = likedTweet.id AND user_id = ${id}) THEN TRUE ELSE FALSE END)` + `(CASE WHEN EXISTS (SELECT 1 FROM Likes WHERE tweet_id = likedTweet.id AND user_id = ${currentUserId}) THEN TRUE ELSE FALSE END)` ), - 'isLiked' - ] + "isLiked", + ], ], include: [ - { model: User, as: 'author' } + { model: User, as: "author" }, // { model: Reply, as: "replies" }, - ] - } - ] - }) - console.log(likes) + ], + }, + ], + }); + console.log(likes); - if (likes.length === 0) { return res.status(200).json({ status: 'success', message: 'No likes' }) } + if (likes.length === 0) { + return res.status(200).json({ status: "success", message: "No likes" }); + } - const likedTweetsData = likes.map(like => ({ + const likedTweetsData = likes.map((like) => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, @@ -325,34 +328,34 @@ const userController = { createdAt: like.likedTweet.createdAt, replyCount: like.likedTweet.replyCount, likeCount: like.likedTweet.likeCount, - isLiked: like.likedTweet.isLiked - })) - res.status(200).json(likedTweetsData) + isLiked: like.likedTweet.isLiked, + })); + res.status(200).json(likedTweetsData); } catch (err) { - next(err) + next(err); } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); const [userTweets] = await Promise.all([ Tweet.findAll({ where: { userId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], attributes: [ - 'id', - 'description', - 'createdAt', - 'updatedAt', + "id", + "description", + "createdAt", + "updatedAt", [ sequelize.literal(`( SELECT COUNT(*) FROM Likes WHERE Likes.tweet_id = Tweet.id )`), - 'likeCount' + "likeCount", ], [ sequelize.literal(`( @@ -360,20 +363,20 @@ const userController = { FROM Replies WHERE Replies.tweet_id = Tweet.id )`), - 'replyCount' - ] + "replyCount", + ], ], include: [ { model: User, - as: 'author', - attributes: { exclude: ['password'] } - } - ] - }) - ]) - console.log(userTweets) - const userTweetsData = userTweets.map(tweet => ({ + as: "author", + attributes: { exclude: ["password"] }, + }, + ], + }), + ]); + console.log(userTweets); + const userTweetsData = userTweets.map((tweet) => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -381,97 +384,97 @@ const userController = { description: tweet.description, createdAt: tweet.createdAt, replyCount: tweet.replyCount, - likeCount: tweet.likeCount - })) + likeCount: tweet.likeCount, + })); - res.status(200).json(userTweetsData) + res.status(200).json(userTweetsData); } catch (err) { - next(err) + next(err); } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params // 18 target + const { id } = req.params; // 18 target const user = await User.findByPk(id, { include: { model: User, - as: 'Followers' - } - }) + as: "Followers", + }, + }); - if (!user) throw new Error('User does not exist') + if (!user) throw new Error("User does not exist"); if (!user.Followers) { return res .status(200) - .json({ status: 'success', message: 'No followers' }) + .json({ status: "success", message: "No followers" }); } - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); const followingIds = currentUserFollowingId.map( - item => item.followingId - ) + (item) => item.followingId + ); - const followersData = user.Followers.map(follower => ({ + const followersData = user.Followers.map((follower) => ({ followerId: follower.id, followerAccount: follower.account, followerName: follower.name, followerAvatar: follower.avatar, isFollowed: followingIds.includes(follower.id), - follower - })) + follower, + })); - res.status(200).json(followersData) + res.status(200).json(followersData); } catch (err) { - next(err) + next(err); } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params + const { id } = req.params; const user = await User.findByPk(id, { include: { model: User, - as: 'Followings' - } - }) - if (!user) throw new Error('User does not exist') + as: "Followings", + }, + }); + if (!user) throw new Error("User does not exist"); if (!user.Followings) { return res .status(200) - .json({ status: 'success', message: 'No followings' }) + .json({ status: "success", message: "No followings" }); } - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); const followingIds = currentUserFollowingId.map( - item => item.followingId - ) + (item) => item.followingId + ); - const followingsData = user.Followings.map(following => ({ + const followingsData = user.Followings.map((following) => ({ followingId: following.id, followingAccount: following.account, followingName: following.name, followingAvatar: following.avatar, isFollowed: followingIds.includes(following.id), - following - })) + following, + })); - res.status(200).json(followingsData) + res.status(200).json(followingsData); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = userController +module.exports = userController; From ebc55a6aaaa847af97064a985f8f01411ff83385 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 1 Sep 2023 10:32:55 +0800 Subject: [PATCH 140/170] fix : is liked boolean --- controllers/apis/user-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index fc3cd1602a..77b7c556ce 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -328,7 +328,7 @@ const userController = { createdAt: like.likedTweet.createdAt, replyCount: like.likedTweet.replyCount, likeCount: like.likedTweet.likeCount, - isLiked: like.likedTweet.isLiked, + isLiked: like.likedTweet.isLiked === 1, })); res.status(200).json(likedTweetsData); } catch (err) { From 5fe46f80daa64715bf8a7aff2c5543e52d74af7f Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 1 Sep 2023 10:49:04 +0800 Subject: [PATCH 141/170] fix: getUserREPLIEDTWEETS --- controllers/apis/user-controller.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 77b7c556ce..b02ca8eae5 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -151,7 +151,12 @@ const userController = { model: Tweet, as: "tweetreply", include: [ - { model: User, as: "author", attributes: ["account", "name"] }, + { + model: User, + as: "author", + attributes: ["account", "name"], + // where: { role: "user" }, + }, ], }, ], @@ -166,10 +171,10 @@ const userController = { const userRepliesResult = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, - replierId: user.id, - replierName: user.name, - replierAvatar: user.avatar, - replierAccount: user.account, + replierId: reply.replier.id, + replierName: reply.replier.name, + replierAvatar: reply.replier.avatar, + replierAccount: reply.replier.account, createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, From 55d15aef70ef30b88056c267ae006900a2f709f1 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 1 Sep 2023 15:00:12 +0800 Subject: [PATCH 142/170] fix: bugs --- controllers/apis/user-controller.js | 396 ++++++++++++++-------------- 1 file changed, 198 insertions(+), 198 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index b02ca8eae5..382c55227f 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,36 +1,36 @@ -const bcrypt = require("bcryptjs"); -const jwt = require("jsonwebtoken"); -const sequelize = require("sequelize"); -const { imgurFileHandler } = require("../../helpers/file-helpers"); +const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') +const sequelize = require('sequelize') +const { imgurFileHandler } = require('../../helpers/file-helpers') -const db = require("../../models"); -const helpers = require("../../_helpers"); +const db = require('../../models') +const helpers = require('../../_helpers') -const { User, Tweet, Reply, Followship, Like } = db; -const { Op } = require("sequelize"); -const like = require("../../models/like"); +const { User, Tweet, Reply, Followship, Like } = db +const { Op } = require('sequelize') +const like = require('../../models/like') const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body; + const { account, name, email, password, checkPassword } = req.body if (!account || !email || !password || !checkPassword) { throw new Error( - "Please enter account, email, password and checkPassword" - ); + 'Please enter account, email, password and checkPassword' + ) } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }], - }, - }); + [Op.or]: [{ email }, { account }] + } + }) if (user) { - if (user.account === account) throw new Error("account 已重複註冊!"); - if (user.email === email) throw new Error("email 已重複註冊!"); + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') } const createdUser = await User.create({ @@ -38,104 +38,104 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: "https://picsum.photos/100/100", - cover: "https://picsum.photos/id/237/700/400", - role: "user", + avatar: 'https://picsum.photos/100/100', + cover: 'https://picsum.photos/id/237/700/400', + role: 'user', createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create user.", - data: createdUser, - }); + status: 'success', + message: 'Successfully create user.', + data: createdUser + }) } catch (err) { - next(err); + next(err) } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body; + const { account, password } = req.body if (!account || !password) { - throw new Error("Please enter account and password"); + throw new Error('Please enter account and password') } - const user = await User.findOne({ where: { account } }); - if (!user) throw new Error("User does not exist"); - if (user.role === "admin") throw new Error("admin permission denied"); + const user = await User.findOne({ where: { account } }) + if (!user) throw new Error('User does not exist') + if (user.role === 'admin') throw new Error('admin permission denied') if (!bcrypt.compareSync(password, user.password)) { - throw new Error("Incorrect password"); + throw new Error('Incorrect password') } const payload = { id: user.id, account: user.account, - role: user.role, - }; + role: user.role + } const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "30d", - }); - const userId = user.toJSON().id; + expiresIn: '30d' + }) + const userId = user.toJSON().id res.status(200).json({ - status: "success", + status: 'success', data: { token, - userId, - }, - }); + userId + } + }) } catch (err) { - next(err); + next(err) } }, getUser: async (req, res, next) => { try { - const { id } = req.params; - const currentUserId = helpers.getUser(req).id; + const { id } = req.params + const currentUserId = helpers.getUser(req).id const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id }, + where: { UserId: id } }), Followship.count({ - where: { followerId: id }, + where: { followerId: id } }), Followship.count({ - where: { followingId: id }, - }), - ]); + where: { followingId: id } + }) + ]) if (!user) { return res .status(401) - .json({ status: "error", message: "This user does not exist" }); + .json({ status: 'error', message: 'This user does not exist' }) } - delete user.password; - user.tweetCount = tweetCount; - user.followerCount = followerCount; - user.followingCount = followingCount; + delete user.password + user.tweetCount = tweetCount + user.followerCount = followerCount + user.followingCount = followingCount if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) user.isFollowed = checkUserFollowing.some( - (follow) => follow.followingId === Number(id) - ); + follow => follow.followingId === Number(id) + ) } - console.log(user); - res.status(200).json(user); + console.log(user) + res.status(200).json(user) } catch (err) { - next(err); + next(err) } }, getUserRepliedTweets: async (req, res, next) => { try { - const userId = req.params.id; + const userId = req.params.id const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -144,31 +144,31 @@ const userController = { include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ { model: User, - as: "author", - attributes: ["account", "name"], + as: 'author', + attributes: ['account', 'name'] // where: { role: "user" }, - }, - ], - }, + } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, + order: [['createdAt', 'DESC']], + nest: true }), Like.findAll({ - where: { userId }, - }), - ]); + where: { userId } + }) + ]) - const userRepliesResult = replies.map((reply) => ({ + const userRepliesResult = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -178,76 +178,76 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(userRepliesResult); + res.status(200).json(userRepliesResult) } catch (err) { - next(err); + next(err) } }, updateUser: async (req, res, next) => { try { - const { id } = req.params; - const { account, name, email, password, introduction } = req.body; + const { id } = req.params + const { account, name, email, password, introduction } = req.body - const user = await User.findByPk(id); + const user = await User.findByPk(id) if (!user) { return res.status(401).json({ - status: "error", - message: "This user does not exist", - }); + status: 'error', + message: 'This user does not exist' + }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id if (!currentUserId) { - throw new Error("Current user ID is missing"); + throw new Error('Current user ID is missing') } if (currentUserId !== Number(id)) { - throw new Error("Cannot edit other users profile"); + throw new Error('Cannot edit other users profile') } if (name && name.length > 50) { - throw new Error("the length of name should less than 50 characters"); + throw new Error('the length of name should less than 50 characters') } if (introduction && introduction.length > 160) { throw new Error( - "the length of introduction should less than 160 characters" - ); + 'the length of introduction should less than 160 characters' + ) } if (account) { const userByAccount = await User.findOne({ where: { account }, raw: true, - nest: true, - }); + nest: true + }) if (userByAccount && userByAccount.account === account) { - throw new Error("account 已重複註冊!"); + throw new Error('account 已重複註冊!') } } if (email) { - const userByEmail = await User.findOne({ where: { email } }); + const userByEmail = await User.findOne({ where: { email } }) if (userByEmail && userByEmail.email === email) { - throw new Error("email 已重複註冊!"); + throw new Error('email 已重複註冊!') } } - const { files } = req; + const { files } = req - let newAvatar = ""; - let newCover = ""; + let newAvatar = '' + let newCover = '' - if (files && files.avatar && files.avatar[0].fieldname === "avatar") { - newAvatar = await imgurFileHandler(files.avatar[0]); + if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { + newAvatar = await imgurFileHandler(files.avatar[0]) } - if (files && files.cover && files.cover[0].fieldname === "cover") { - newCover = await imgurFileHandler(files.cover[0]); + if (files && files.cover && files.cover[0].fieldname === 'cover') { + newCover = await imgurFileHandler(files.cover[0]) } await user.update({ @@ -257,23 +257,23 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover, - }); + cover: newCover || user.cover + }) res.status(200).json({ - status: "success", - message: "Successfully update user.", - data: user, - }); + status: 'success', + message: 'Successfully update user.', + data: user + }) } catch (err) { - next(err); + next(err) } }, getUserLikes: async (req, res, next) => { try { - const currentUserId = helpers.getUser(req).id; - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const currentUserId = helpers.getUser(req).id + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const likes = await Like.findAll({ where: { userId: id }, raw: true, @@ -285,46 +285,46 @@ const userController = { // }, { model: Tweet, - as: "likedTweet", + as: 'likedTweet', attributes: [ - "id", - "UserId", - "description", - "createdAt", - "updatedAt", + 'id', + 'UserId', + 'description', + 'createdAt', + 'updatedAt', [ sequelize.literal( - "(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)" + '(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)' ), - "replyCount", + 'replyCount' ], [ sequelize.literal( - "(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)" + '(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)' ), - "likeCount", + 'likeCount' ], [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Likes WHERE tweet_id = likedTweet.id AND user_id = ${currentUserId}) THEN TRUE ELSE FALSE END)` ), - "isLiked", - ], + 'isLiked' + ] ], include: [ - { model: User, as: "author" }, + { model: User, as: 'author' } // { model: Reply, as: "replies" }, - ], - }, - ], - }); - console.log(likes); + ] + } + ] + }) + console.log(likes) if (likes.length === 0) { - return res.status(200).json({ status: "success", message: "No likes" }); + return res.status(200).json({ status: 'success', message: 'No likes' }) } - const likedTweetsData = likes.map((like) => ({ + const likedTweetsData = likes.map(like => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, @@ -333,34 +333,34 @@ const userController = { createdAt: like.likedTweet.createdAt, replyCount: like.likedTweet.replyCount, likeCount: like.likedTweet.likeCount, - isLiked: like.likedTweet.isLiked === 1, - })); - res.status(200).json(likedTweetsData); + isLiked: like.likedTweet.isLiked === 1 + })) + res.status(200).json(likedTweetsData) } catch (err) { - next(err); + next(err) } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const [userTweets] = await Promise.all([ Tweet.findAll({ where: { userId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], attributes: [ - "id", - "description", - "createdAt", - "updatedAt", + 'id', + 'description', + 'createdAt', + 'updatedAt', [ sequelize.literal(`( SELECT COUNT(*) FROM Likes WHERE Likes.tweet_id = Tweet.id )`), - "likeCount", + 'likeCount' ], [ sequelize.literal(`( @@ -368,20 +368,20 @@ const userController = { FROM Replies WHERE Replies.tweet_id = Tweet.id )`), - "replyCount", - ], + 'replyCount' + ] ], include: [ { model: User, - as: "author", - attributes: { exclude: ["password"] }, - }, - ], - }), - ]); - console.log(userTweets); - const userTweetsData = userTweets.map((tweet) => ({ + as: 'author', + attributes: { exclude: ['password'] } + } + ] + }) + ]) + console.log(userTweets) + const userTweetsData = userTweets.map(tweet => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -389,97 +389,97 @@ const userController = { description: tweet.description, createdAt: tweet.createdAt, replyCount: tweet.replyCount, - likeCount: tweet.likeCount, - })); + likeCount: tweet.likeCount + })) - res.status(200).json(userTweetsData); + res.status(200).json(userTweetsData) } catch (err) { - next(err); + next(err) } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params; // 18 target + const { id } = req.params // 18 target const user = await User.findByPk(id, { include: { model: User, - as: "Followers", - }, - }); + as: 'Followers' + } + }) - if (!user) throw new Error("User does not exist"); + if (!user) throw new Error('User does not exist') if (!user.Followers) { return res .status(200) - .json({ status: "success", message: "No followers" }); + .json({ status: 'success', message: 'No followers' }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) const followingIds = currentUserFollowingId.map( - (item) => item.followingId - ); + item => item.followingId + ) - const followersData = user.Followers.map((follower) => ({ + const followersData = user.Followers.map(follower => ({ followerId: follower.id, followerAccount: follower.account, followerName: follower.name, followerAvatar: follower.avatar, isFollowed: followingIds.includes(follower.id), - follower, - })); + follower + })) - res.status(200).json(followersData); + res.status(200).json(followersData) } catch (err) { - next(err); + next(err) } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params; + const { id } = req.params const user = await User.findByPk(id, { include: { model: User, - as: "Followings", - }, - }); - if (!user) throw new Error("User does not exist"); + as: 'Followings' + } + }) + if (!user) throw new Error('User does not exist') if (!user.Followings) { return res .status(200) - .json({ status: "success", message: "No followings" }); + .json({ status: 'success', message: 'No followings' }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) const followingIds = currentUserFollowingId.map( - (item) => item.followingId - ); + item => item.followingId + ) - const followingsData = user.Followings.map((following) => ({ + const followingsData = user.Followings.map(following => ({ followingId: following.id, followingAccount: following.account, followingName: following.name, followingAvatar: following.avatar, isFollowed: followingIds.includes(following.id), - following, - })); + following + })) - res.status(200).json(followingsData); + res.status(200).json(followingsData) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = userController; +module.exports = userController From 274898c6827fc03ae784207404f9626ab1a95fba Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 1 Sep 2023 15:42:16 +0800 Subject: [PATCH 143/170] fix: top 10 repeated data --- controllers/apis/followship-controller.js | 8 -------- seeders/20230821044414-users-seed-file.js | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index fc5bee3ba4..a20b95146c 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -88,14 +88,6 @@ const followshipController = { 'isFollowed' ] ], - include: [ - { - model: User, - as: 'Followers', - attributes: [], - through: { attributes: [] } - } - ], order: [[sequelize.literal('totalFollowers'), 'DESC']], limit: 10, subQuery: false, // 避免因查詢多張表造成limit失常 diff --git a/seeders/20230821044414-users-seed-file.js b/seeders/20230821044414-users-seed-file.js index c1fee92b62..62c9a3d636 100644 --- a/seeders/20230821044414-users-seed-file.js +++ b/seeders/20230821044414-users-seed-file.js @@ -13,7 +13,7 @@ module.exports = { role: 'admin', name: 'Admin', account: 'root', - avatar: `https://loremflickr.com/150/150/boy/?random=${ + avatar: `https://loremflickr.com/150/150/cat/?random=${ Math.random() * 100 }`, cover: `https://loremflickr.com/1480/480/city/?random=${ @@ -33,7 +33,7 @@ module.exports = { role: 'user', name: `User${i}`, account: `user${i}`, - avatar: `https://loremflickr.com/150/150/boy/?random=${ + avatar: `https://loremflickr.com/150/150/cat/?random=${ Math.random() * 100 }`, cover: `https://loremflickr.com/1440/480/city/?random=${ From 9adc3a2eb058081c8faa3264533e3bc4700bff7d Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 1 Sep 2023 17:02:14 +0800 Subject: [PATCH 144/170] fix: new account avatar --- controllers/apis/user-controller.js | 398 ++++++++++++++-------------- 1 file changed, 200 insertions(+), 198 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 382c55227f..72f2788b61 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,36 +1,36 @@ -const bcrypt = require('bcryptjs') -const jwt = require('jsonwebtoken') -const sequelize = require('sequelize') -const { imgurFileHandler } = require('../../helpers/file-helpers') +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken"); +const sequelize = require("sequelize"); +const { imgurFileHandler } = require("../../helpers/file-helpers"); -const db = require('../../models') -const helpers = require('../../_helpers') +const db = require("../../models"); +const helpers = require("../../_helpers"); -const { User, Tweet, Reply, Followship, Like } = db -const { Op } = require('sequelize') -const like = require('../../models/like') +const { User, Tweet, Reply, Followship, Like } = db; +const { Op } = require("sequelize"); +const like = require("../../models/like"); const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body + const { account, name, email, password, checkPassword } = req.body; if (!account || !email || !password || !checkPassword) { throw new Error( - 'Please enter account, email, password and checkPassword' - ) + "Please enter account, email, password and checkPassword" + ); } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }] - } - }) + [Op.or]: [{ email }, { account }], + }, + }); if (user) { - if (user.account === account) throw new Error('account 已重複註冊!') - if (user.email === email) throw new Error('email 已重複註冊!') + if (user.account === account) throw new Error("account 已重複註冊!"); + if (user.email === email) throw new Error("email 已重複註冊!"); } const createdUser = await User.create({ @@ -38,104 +38,106 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: 'https://picsum.photos/100/100', - cover: 'https://picsum.photos/id/237/700/400', - role: 'user', + avatar: `https://picsum.photos/100/100/cat/?random=${ + Math.random() * 100 + }`, + cover: "https://picsum.photos/id/237/700/400", + role: "user", createdAt: new Date(), - updatedAt: new Date() - }) + updatedAt: new Date(), + }); res.status(200).json({ - status: 'success', - message: 'Successfully create user.', - data: createdUser - }) + status: "success", + message: "Successfully create user.", + data: createdUser, + }); } catch (err) { - next(err) + next(err); } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body + const { account, password } = req.body; if (!account || !password) { - throw new Error('Please enter account and password') + throw new Error("Please enter account and password"); } - const user = await User.findOne({ where: { account } }) - if (!user) throw new Error('User does not exist') - if (user.role === 'admin') throw new Error('admin permission denied') + const user = await User.findOne({ where: { account } }); + if (!user) throw new Error("User does not exist"); + if (user.role === "admin") throw new Error("admin permission denied"); if (!bcrypt.compareSync(password, user.password)) { - throw new Error('Incorrect password') + throw new Error("Incorrect password"); } const payload = { id: user.id, account: user.account, - role: user.role - } + role: user.role, + }; const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: '30d' - }) - const userId = user.toJSON().id + expiresIn: "30d", + }); + const userId = user.toJSON().id; res.status(200).json({ - status: 'success', + status: "success", data: { token, - userId - } - }) + userId, + }, + }); } catch (err) { - next(err) + next(err); } }, getUser: async (req, res, next) => { try { - const { id } = req.params - const currentUserId = helpers.getUser(req).id + const { id } = req.params; + const currentUserId = helpers.getUser(req).id; const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id } + where: { UserId: id }, }), Followship.count({ - where: { followerId: id } + where: { followerId: id }, }), Followship.count({ - where: { followingId: id } - }) - ]) + where: { followingId: id }, + }), + ]); if (!user) { return res .status(401) - .json({ status: 'error', message: 'This user does not exist' }) + .json({ status: "error", message: "This user does not exist" }); } - delete user.password - user.tweetCount = tweetCount - user.followerCount = followerCount - user.followingCount = followingCount + delete user.password; + user.tweetCount = tweetCount; + user.followerCount = followerCount; + user.followingCount = followingCount; if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); user.isFollowed = checkUserFollowing.some( - follow => follow.followingId === Number(id) - ) + (follow) => follow.followingId === Number(id) + ); } - console.log(user) - res.status(200).json(user) + console.log(user); + res.status(200).json(user); } catch (err) { - next(err) + next(err); } }, getUserRepliedTweets: async (req, res, next) => { try { - const userId = req.params.id + const userId = req.params.id; const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -144,31 +146,31 @@ const userController = { include: [ { model: User, - as: 'replier', - attributes: { exclude: ['password'] } + as: "replier", + attributes: { exclude: ["password"] }, }, { model: Tweet, - as: 'tweetreply', + as: "tweetreply", include: [ { model: User, - as: 'author', - attributes: ['account', 'name'] + as: "author", + attributes: ["account", "name"], // where: { role: "user" }, - } - ] - } + }, + ], + }, ], - order: [['createdAt', 'DESC']], - nest: true + order: [["createdAt", "DESC"]], + nest: true, }), Like.findAll({ - where: { userId } - }) - ]) + where: { userId }, + }), + ]); - const userRepliesResult = replies.map(reply => ({ + const userRepliesResult = replies.map((reply) => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -178,76 +180,76 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account - })) + tweetBelongerAccount: reply.tweetreply.author.account, + })); - res.status(200).json(userRepliesResult) + res.status(200).json(userRepliesResult); } catch (err) { - next(err) + next(err); } }, updateUser: async (req, res, next) => { try { - const { id } = req.params - const { account, name, email, password, introduction } = req.body + const { id } = req.params; + const { account, name, email, password, introduction } = req.body; - const user = await User.findByPk(id) + const user = await User.findByPk(id); if (!user) { return res.status(401).json({ - status: 'error', - message: 'This user does not exist' - }) + status: "error", + message: "This user does not exist", + }); } - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; if (!currentUserId) { - throw new Error('Current user ID is missing') + throw new Error("Current user ID is missing"); } if (currentUserId !== Number(id)) { - throw new Error('Cannot edit other users profile') + throw new Error("Cannot edit other users profile"); } if (name && name.length > 50) { - throw new Error('the length of name should less than 50 characters') + throw new Error("the length of name should less than 50 characters"); } if (introduction && introduction.length > 160) { throw new Error( - 'the length of introduction should less than 160 characters' - ) + "the length of introduction should less than 160 characters" + ); } if (account) { const userByAccount = await User.findOne({ where: { account }, raw: true, - nest: true - }) + nest: true, + }); if (userByAccount && userByAccount.account === account) { - throw new Error('account 已重複註冊!') + throw new Error("account 已重複註冊!"); } } if (email) { - const userByEmail = await User.findOne({ where: { email } }) + const userByEmail = await User.findOne({ where: { email } }); if (userByEmail && userByEmail.email === email) { - throw new Error('email 已重複註冊!') + throw new Error("email 已重複註冊!"); } } - const { files } = req + const { files } = req; - let newAvatar = '' - let newCover = '' + let newAvatar = ""; + let newCover = ""; - if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { - newAvatar = await imgurFileHandler(files.avatar[0]) + if (files && files.avatar && files.avatar[0].fieldname === "avatar") { + newAvatar = await imgurFileHandler(files.avatar[0]); } - if (files && files.cover && files.cover[0].fieldname === 'cover') { - newCover = await imgurFileHandler(files.cover[0]) + if (files && files.cover && files.cover[0].fieldname === "cover") { + newCover = await imgurFileHandler(files.cover[0]); } await user.update({ @@ -257,23 +259,23 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover - }) + cover: newCover || user.cover, + }); res.status(200).json({ - status: 'success', - message: 'Successfully update user.', - data: user - }) + status: "success", + message: "Successfully update user.", + data: user, + }); } catch (err) { - next(err) + next(err); } }, getUserLikes: async (req, res, next) => { try { - const currentUserId = helpers.getUser(req).id - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const currentUserId = helpers.getUser(req).id; + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); const likes = await Like.findAll({ where: { userId: id }, raw: true, @@ -285,46 +287,46 @@ const userController = { // }, { model: Tweet, - as: 'likedTweet', + as: "likedTweet", attributes: [ - 'id', - 'UserId', - 'description', - 'createdAt', - 'updatedAt', + "id", + "UserId", + "description", + "createdAt", + "updatedAt", [ sequelize.literal( - '(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)' + "(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)" ), - 'replyCount' + "replyCount", ], [ sequelize.literal( - '(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)' + "(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)" ), - 'likeCount' + "likeCount", ], [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Likes WHERE tweet_id = likedTweet.id AND user_id = ${currentUserId}) THEN TRUE ELSE FALSE END)` ), - 'isLiked' - ] + "isLiked", + ], ], include: [ - { model: User, as: 'author' } + { model: User, as: "author" }, // { model: Reply, as: "replies" }, - ] - } - ] - }) - console.log(likes) + ], + }, + ], + }); + console.log(likes); if (likes.length === 0) { - return res.status(200).json({ status: 'success', message: 'No likes' }) + return res.status(200).json({ status: "success", message: "No likes" }); } - const likedTweetsData = likes.map(like => ({ + const likedTweetsData = likes.map((like) => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, @@ -333,34 +335,34 @@ const userController = { createdAt: like.likedTweet.createdAt, replyCount: like.likedTweet.replyCount, likeCount: like.likedTweet.likeCount, - isLiked: like.likedTweet.isLiked === 1 - })) - res.status(200).json(likedTweetsData) + isLiked: like.likedTweet.isLiked === 1, + })); + res.status(200).json(likedTweetsData); } catch (err) { - next(err) + next(err); } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params - const user = await User.findByPk(id, { raw: true, nest: true }) - if (!user) throw new Error('User does not exist') + const { id } = req.params; + const user = await User.findByPk(id, { raw: true, nest: true }); + if (!user) throw new Error("User does not exist"); const [userTweets] = await Promise.all([ Tweet.findAll({ where: { userId: id }, - order: [['createdAt', 'DESC']], + order: [["createdAt", "DESC"]], attributes: [ - 'id', - 'description', - 'createdAt', - 'updatedAt', + "id", + "description", + "createdAt", + "updatedAt", [ sequelize.literal(`( SELECT COUNT(*) FROM Likes WHERE Likes.tweet_id = Tweet.id )`), - 'likeCount' + "likeCount", ], [ sequelize.literal(`( @@ -368,20 +370,20 @@ const userController = { FROM Replies WHERE Replies.tweet_id = Tweet.id )`), - 'replyCount' - ] + "replyCount", + ], ], include: [ { model: User, - as: 'author', - attributes: { exclude: ['password'] } - } - ] - }) - ]) - console.log(userTweets) - const userTweetsData = userTweets.map(tweet => ({ + as: "author", + attributes: { exclude: ["password"] }, + }, + ], + }), + ]); + console.log(userTweets); + const userTweetsData = userTweets.map((tweet) => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -389,97 +391,97 @@ const userController = { description: tweet.description, createdAt: tweet.createdAt, replyCount: tweet.replyCount, - likeCount: tweet.likeCount - })) + likeCount: tweet.likeCount, + })); - res.status(200).json(userTweetsData) + res.status(200).json(userTweetsData); } catch (err) { - next(err) + next(err); } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params // 18 target + const { id } = req.params; // 18 target const user = await User.findByPk(id, { include: { model: User, - as: 'Followers' - } - }) + as: "Followers", + }, + }); - if (!user) throw new Error('User does not exist') + if (!user) throw new Error("User does not exist"); if (!user.Followers) { return res .status(200) - .json({ status: 'success', message: 'No followers' }) + .json({ status: "success", message: "No followers" }); } - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); const followingIds = currentUserFollowingId.map( - item => item.followingId - ) + (item) => item.followingId + ); - const followersData = user.Followers.map(follower => ({ + const followersData = user.Followers.map((follower) => ({ followerId: follower.id, followerAccount: follower.account, followerName: follower.name, followerAvatar: follower.avatar, isFollowed: followingIds.includes(follower.id), - follower - })) + follower, + })); - res.status(200).json(followersData) + res.status(200).json(followersData); } catch (err) { - next(err) + next(err); } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params + const { id } = req.params; const user = await User.findByPk(id, { include: { model: User, - as: 'Followings' - } - }) - if (!user) throw new Error('User does not exist') + as: "Followings", + }, + }); + if (!user) throw new Error("User does not exist"); if (!user.Followings) { return res .status(200) - .json({ status: 'success', message: 'No followings' }) + .json({ status: "success", message: "No followings" }); } - const currentUserId = helpers.getUser(req).id + const currentUserId = helpers.getUser(req).id; const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true - }) + raw: true, + }); const followingIds = currentUserFollowingId.map( - item => item.followingId - ) + (item) => item.followingId + ); - const followingsData = user.Followings.map(following => ({ + const followingsData = user.Followings.map((following) => ({ followingId: following.id, followingAccount: following.account, followingName: following.name, followingAvatar: following.avatar, isFollowed: followingIds.includes(following.id), - following - })) + following, + })); - res.status(200).json(followingsData) + res.status(200).json(followingsData); } catch (err) { - next(err) + next(err); } - } -} + }, +}; -module.exports = userController +module.exports = userController; From d0214397f1351762b79fe6500565aa7693dc22a1 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 1 Sep 2023 17:06:34 +0800 Subject: [PATCH 145/170] fix: bugs --- controllers/apis/user-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 72f2788b61..176f516088 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -38,7 +38,7 @@ const userController = { email, account, password: bcrypt.hashSync(password, 10), - avatar: `https://picsum.photos/100/100/cat/?random=${ + avatar: `https://loremflickr.com/150/150/cat/?random=${ Math.random() * 100 }`, cover: "https://picsum.photos/id/237/700/400", From 39e11c859f730011bd18edafb075bb1e7f05bfeb Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Fri, 1 Sep 2023 23:04:29 +0800 Subject: [PATCH 146/170] style: error --- controllers/apis/user-controller.js | 394 ++++++++++++++-------------- middleware/error-handler.js | 2 +- 2 files changed, 198 insertions(+), 198 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 176f516088..35adabc6cc 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,36 +1,36 @@ -const bcrypt = require("bcryptjs"); -const jwt = require("jsonwebtoken"); -const sequelize = require("sequelize"); -const { imgurFileHandler } = require("../../helpers/file-helpers"); +const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') +const sequelize = require('sequelize') +const { imgurFileHandler } = require('../../helpers/file-helpers') -const db = require("../../models"); -const helpers = require("../../_helpers"); +const db = require('../../models') +const helpers = require('../../_helpers') -const { User, Tweet, Reply, Followship, Like } = db; -const { Op } = require("sequelize"); -const like = require("../../models/like"); +const { User, Tweet, Reply, Followship, Like } = db +const { Op } = require('sequelize') +const like = require('../../models/like') const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body; + const { account, name, email, password, checkPassword } = req.body if (!account || !email || !password || !checkPassword) { throw new Error( - "Please enter account, email, password and checkPassword" - ); + 'Please enter account, email, password and checkPassword' + ) } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }], - }, - }); + [Op.or]: [{ email }, { account }] + } + }) if (user) { - if (user.account === account) throw new Error("account 已重複註冊!"); - if (user.email === email) throw new Error("email 已重複註冊!"); + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') } const createdUser = await User.create({ @@ -41,103 +41,103 @@ const userController = { avatar: `https://loremflickr.com/150/150/cat/?random=${ Math.random() * 100 }`, - cover: "https://picsum.photos/id/237/700/400", - role: "user", + cover: 'https://picsum.photos/id/237/700/400', + role: 'user', createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create user.", - data: createdUser, - }); + status: 'success', + message: 'Successfully create user.', + data: createdUser + }) } catch (err) { - next(err); + next(err) } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body; + const { account, password } = req.body if (!account || !password) { - throw new Error("Please enter account and password"); + throw new Error('Please enter account and password') } - const user = await User.findOne({ where: { account } }); - if (!user) throw new Error("User does not exist"); - if (user.role === "admin") throw new Error("admin permission denied"); + const user = await User.findOne({ where: { account } }) + if (!user) throw new Error('User does not exist') + if (user.role === 'admin') throw new Error('admin permission denied') if (!bcrypt.compareSync(password, user.password)) { - throw new Error("Incorrect password"); + throw new Error('Incorrect password') } const payload = { id: user.id, account: user.account, - role: user.role, - }; + role: user.role + } const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "30d", - }); - const userId = user.toJSON().id; + expiresIn: '30d' + }) + const userId = user.toJSON().id res.status(200).json({ - status: "success", + status: 'success', data: { token, - userId, - }, - }); + userId + } + }) } catch (err) { - next(err); + next(err) } }, getUser: async (req, res, next) => { try { - const { id } = req.params; - const currentUserId = helpers.getUser(req).id; + const { id } = req.params + const currentUserId = helpers.getUser(req).id const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id }, + where: { UserId: id } }), Followship.count({ - where: { followerId: id }, + where: { followerId: id } }), Followship.count({ - where: { followingId: id }, - }), - ]); + where: { followingId: id } + }) + ]) if (!user) { return res .status(401) - .json({ status: "error", message: "This user does not exist" }); + .json({ status: 'error', message: 'This user does not exist' }) } - delete user.password; - user.tweetCount = tweetCount; - user.followerCount = followerCount; - user.followingCount = followingCount; + delete user.password + user.tweetCount = tweetCount + user.followerCount = followerCount + user.followingCount = followingCount if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) user.isFollowed = checkUserFollowing.some( - (follow) => follow.followingId === Number(id) - ); + follow => follow.followingId === Number(id) + ) } - console.log(user); - res.status(200).json(user); + console.log(user) + res.status(200).json(user) } catch (err) { - next(err); + next(err) } }, getUserRepliedTweets: async (req, res, next) => { try { - const userId = req.params.id; + const userId = req.params.id const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -146,31 +146,31 @@ const userController = { include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ { model: User, - as: "author", - attributes: ["account", "name"], + as: 'author', + attributes: ['account', 'name'] // where: { role: "user" }, - }, - ], - }, + } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, + order: [['createdAt', 'DESC']], + nest: true }), Like.findAll({ - where: { userId }, - }), - ]); + where: { userId } + }) + ]) - const userRepliesResult = replies.map((reply) => ({ + const userRepliesResult = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -180,76 +180,76 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(userRepliesResult); + res.status(200).json(userRepliesResult) } catch (err) { - next(err); + next(err) } }, updateUser: async (req, res, next) => { try { - const { id } = req.params; - const { account, name, email, password, introduction } = req.body; + const { id } = req.params + const { account, name, email, password, introduction } = req.body - const user = await User.findByPk(id); + const user = await User.findByPk(id) if (!user) { return res.status(401).json({ - status: "error", - message: "This user does not exist", - }); + status: 'error', + message: 'This user does not exist' + }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id if (!currentUserId) { - throw new Error("Current user ID is missing"); + throw new Error('Current user ID is missing') } if (currentUserId !== Number(id)) { - throw new Error("Cannot edit other users profile"); + throw new Error('Cannot edit other users profile') } if (name && name.length > 50) { - throw new Error("the length of name should less than 50 characters"); + throw new Error('the length of name should less than 50 characters') } if (introduction && introduction.length > 160) { throw new Error( - "the length of introduction should less than 160 characters" - ); + 'the length of introduction should less than 160 characters' + ) } if (account) { const userByAccount = await User.findOne({ where: { account }, raw: true, - nest: true, - }); + nest: true + }) if (userByAccount && userByAccount.account === account) { - throw new Error("account 已重複註冊!"); + throw new Error('account 已重複註冊!') } } if (email) { - const userByEmail = await User.findOne({ where: { email } }); + const userByEmail = await User.findOne({ where: { email } }) if (userByEmail && userByEmail.email === email) { - throw new Error("email 已重複註冊!"); + throw new Error('email 已重複註冊!') } } - const { files } = req; + const { files } = req - let newAvatar = ""; - let newCover = ""; + let newAvatar = '' + let newCover = '' - if (files && files.avatar && files.avatar[0].fieldname === "avatar") { - newAvatar = await imgurFileHandler(files.avatar[0]); + if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { + newAvatar = await imgurFileHandler(files.avatar[0]) } - if (files && files.cover && files.cover[0].fieldname === "cover") { - newCover = await imgurFileHandler(files.cover[0]); + if (files && files.cover && files.cover[0].fieldname === 'cover') { + newCover = await imgurFileHandler(files.cover[0]) } await user.update({ @@ -259,23 +259,23 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover, - }); + cover: newCover || user.cover + }) res.status(200).json({ - status: "success", - message: "Successfully update user.", - data: user, - }); + status: 'success', + message: 'Successfully update user.', + data: user + }) } catch (err) { - next(err); + next(err) } }, getUserLikes: async (req, res, next) => { try { - const currentUserId = helpers.getUser(req).id; - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const currentUserId = helpers.getUser(req).id + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const likes = await Like.findAll({ where: { userId: id }, raw: true, @@ -287,46 +287,46 @@ const userController = { // }, { model: Tweet, - as: "likedTweet", + as: 'likedTweet', attributes: [ - "id", - "UserId", - "description", - "createdAt", - "updatedAt", + 'id', + 'UserId', + 'description', + 'createdAt', + 'updatedAt', [ sequelize.literal( - "(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)" + '(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)' ), - "replyCount", + 'replyCount' ], [ sequelize.literal( - "(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)" + '(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)' ), - "likeCount", + 'likeCount' ], [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Likes WHERE tweet_id = likedTweet.id AND user_id = ${currentUserId}) THEN TRUE ELSE FALSE END)` ), - "isLiked", - ], + 'isLiked' + ] ], include: [ - { model: User, as: "author" }, + { model: User, as: 'author' } // { model: Reply, as: "replies" }, - ], - }, - ], - }); - console.log(likes); + ] + } + ] + }) + console.log(likes) if (likes.length === 0) { - return res.status(200).json({ status: "success", message: "No likes" }); + return res.status(200).json({ status: 'success', message: 'No likes' }) } - const likedTweetsData = likes.map((like) => ({ + const likedTweetsData = likes.map(like => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, @@ -335,34 +335,34 @@ const userController = { createdAt: like.likedTweet.createdAt, replyCount: like.likedTweet.replyCount, likeCount: like.likedTweet.likeCount, - isLiked: like.likedTweet.isLiked === 1, - })); - res.status(200).json(likedTweetsData); + isLiked: like.likedTweet.isLiked === 1 + })) + res.status(200).json(likedTweetsData) } catch (err) { - next(err); + next(err) } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const [userTweets] = await Promise.all([ Tweet.findAll({ where: { userId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], attributes: [ - "id", - "description", - "createdAt", - "updatedAt", + 'id', + 'description', + 'createdAt', + 'updatedAt', [ sequelize.literal(`( SELECT COUNT(*) FROM Likes WHERE Likes.tweet_id = Tweet.id )`), - "likeCount", + 'likeCount' ], [ sequelize.literal(`( @@ -370,20 +370,20 @@ const userController = { FROM Replies WHERE Replies.tweet_id = Tweet.id )`), - "replyCount", - ], + 'replyCount' + ] ], include: [ { model: User, - as: "author", - attributes: { exclude: ["password"] }, - }, - ], - }), - ]); - console.log(userTweets); - const userTweetsData = userTweets.map((tweet) => ({ + as: 'author', + attributes: { exclude: ['password'] } + } + ] + }) + ]) + console.log(userTweets) + const userTweetsData = userTweets.map(tweet => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -391,97 +391,97 @@ const userController = { description: tweet.description, createdAt: tweet.createdAt, replyCount: tweet.replyCount, - likeCount: tweet.likeCount, - })); + likeCount: tweet.likeCount + })) - res.status(200).json(userTweetsData); + res.status(200).json(userTweetsData) } catch (err) { - next(err); + next(err) } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params; // 18 target + const { id } = req.params // 18 target const user = await User.findByPk(id, { include: { model: User, - as: "Followers", - }, - }); + as: 'Followers' + } + }) - if (!user) throw new Error("User does not exist"); + if (!user) throw new Error('User does not exist') if (!user.Followers) { return res .status(200) - .json({ status: "success", message: "No followers" }); + .json({ status: 'success', message: 'No followers' }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) const followingIds = currentUserFollowingId.map( - (item) => item.followingId - ); + item => item.followingId + ) - const followersData = user.Followers.map((follower) => ({ + const followersData = user.Followers.map(follower => ({ followerId: follower.id, followerAccount: follower.account, followerName: follower.name, followerAvatar: follower.avatar, isFollowed: followingIds.includes(follower.id), - follower, - })); + follower + })) - res.status(200).json(followersData); + res.status(200).json(followersData) } catch (err) { - next(err); + next(err) } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params; + const { id } = req.params const user = await User.findByPk(id, { include: { model: User, - as: "Followings", - }, - }); - if (!user) throw new Error("User does not exist"); + as: 'Followings' + } + }) + if (!user) throw new Error('User does not exist') if (!user.Followings) { return res .status(200) - .json({ status: "success", message: "No followings" }); + .json({ status: 'success', message: 'No followings' }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) const followingIds = currentUserFollowingId.map( - (item) => item.followingId - ); + item => item.followingId + ) - const followingsData = user.Followings.map((following) => ({ + const followingsData = user.Followings.map(following => ({ followingId: following.id, followingAccount: following.account, followingName: following.name, followingAvatar: following.avatar, isFollowed: followingIds.includes(following.id), - following, - })); + following + })) - res.status(200).json(followingsData); + res.status(200).json(followingsData) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = userController; +module.exports = userController diff --git a/middleware/error-handler.js b/middleware/error-handler.js index 7014320dd0..24dbfb2017 100644 --- a/middleware/error-handler.js +++ b/middleware/error-handler.js @@ -3,7 +3,7 @@ module.exports = { if (err instanceof Error) { res.status(err.status || 500).json({ status: 'error', - message: `${err.name}: ${err.message}` + message: `${err.message}` }) // if (err.message === "帳號不存在") { // return res.status(200).json({ From 5c8f815a6ff68eef96b50321d6e4f2dc15507c00 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 1 Sep 2023 23:07:29 +0800 Subject: [PATCH 147/170] fix: test database points to test --- controllers/apis/user-controller.js | 394 ++++++++++++++-------------- models/index.js | 21 +- package.json | 2 +- 3 files changed, 213 insertions(+), 204 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 176f516088..35adabc6cc 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -1,36 +1,36 @@ -const bcrypt = require("bcryptjs"); -const jwt = require("jsonwebtoken"); -const sequelize = require("sequelize"); -const { imgurFileHandler } = require("../../helpers/file-helpers"); +const bcrypt = require('bcryptjs') +const jwt = require('jsonwebtoken') +const sequelize = require('sequelize') +const { imgurFileHandler } = require('../../helpers/file-helpers') -const db = require("../../models"); -const helpers = require("../../_helpers"); +const db = require('../../models') +const helpers = require('../../_helpers') -const { User, Tweet, Reply, Followship, Like } = db; -const { Op } = require("sequelize"); -const like = require("../../models/like"); +const { User, Tweet, Reply, Followship, Like } = db +const { Op } = require('sequelize') +const like = require('../../models/like') const userController = { signUp: async (req, res, next) => { try { - const { account, name, email, password, checkPassword } = req.body; + const { account, name, email, password, checkPassword } = req.body if (!account || !email || !password || !checkPassword) { throw new Error( - "Please enter account, email, password and checkPassword" - ); + 'Please enter account, email, password and checkPassword' + ) } // 檢查帳號是否重複 const user = await User.findOne({ where: { - [Op.or]: [{ email }, { account }], - }, - }); + [Op.or]: [{ email }, { account }] + } + }) if (user) { - if (user.account === account) throw new Error("account 已重複註冊!"); - if (user.email === email) throw new Error("email 已重複註冊!"); + if (user.account === account) throw new Error('account 已重複註冊!') + if (user.email === email) throw new Error('email 已重複註冊!') } const createdUser = await User.create({ @@ -41,103 +41,103 @@ const userController = { avatar: `https://loremflickr.com/150/150/cat/?random=${ Math.random() * 100 }`, - cover: "https://picsum.photos/id/237/700/400", - role: "user", + cover: 'https://picsum.photos/id/237/700/400', + role: 'user', createdAt: new Date(), - updatedAt: new Date(), - }); + updatedAt: new Date() + }) res.status(200).json({ - status: "success", - message: "Successfully create user.", - data: createdUser, - }); + status: 'success', + message: 'Successfully create user.', + data: createdUser + }) } catch (err) { - next(err); + next(err) } }, signIn: async (req, res, next) => { try { - const { account, password } = req.body; + const { account, password } = req.body if (!account || !password) { - throw new Error("Please enter account and password"); + throw new Error('Please enter account and password') } - const user = await User.findOne({ where: { account } }); - if (!user) throw new Error("User does not exist"); - if (user.role === "admin") throw new Error("admin permission denied"); + const user = await User.findOne({ where: { account } }) + if (!user) throw new Error('User does not exist') + if (user.role === 'admin') throw new Error('admin permission denied') if (!bcrypt.compareSync(password, user.password)) { - throw new Error("Incorrect password"); + throw new Error('Incorrect password') } const payload = { id: user.id, account: user.account, - role: user.role, - }; + role: user.role + } const token = jwt.sign(payload, process.env.JWT_SECRET, { - expiresIn: "30d", - }); - const userId = user.toJSON().id; + expiresIn: '30d' + }) + const userId = user.toJSON().id res.status(200).json({ - status: "success", + status: 'success', data: { token, - userId, - }, - }); + userId + } + }) } catch (err) { - next(err); + next(err) } }, getUser: async (req, res, next) => { try { - const { id } = req.params; - const currentUserId = helpers.getUser(req).id; + const { id } = req.params + const currentUserId = helpers.getUser(req).id const [user, tweetCount, followerCount, followingCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ - where: { UserId: id }, + where: { UserId: id } }), Followship.count({ - where: { followerId: id }, + where: { followerId: id } }), Followship.count({ - where: { followingId: id }, - }), - ]); + where: { followingId: id } + }) + ]) if (!user) { return res .status(401) - .json({ status: "error", message: "This user does not exist" }); + .json({ status: 'error', message: 'This user does not exist' }) } - delete user.password; - user.tweetCount = tweetCount; - user.followerCount = followerCount; - user.followingCount = followingCount; + delete user.password + user.tweetCount = tweetCount + user.followerCount = followerCount + user.followingCount = followingCount if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) user.isFollowed = checkUserFollowing.some( - (follow) => follow.followingId === Number(id) - ); + follow => follow.followingId === Number(id) + ) } - console.log(user); - res.status(200).json(user); + console.log(user) + res.status(200).json(user) } catch (err) { - next(err); + next(err) } }, getUserRepliedTweets: async (req, res, next) => { try { - const userId = req.params.id; + const userId = req.params.id const [user, replies] = await Promise.all([ User.findByPk(userId, { raw: true, nest: true }), @@ -146,31 +146,31 @@ const userController = { include: [ { model: User, - as: "replier", - attributes: { exclude: ["password"] }, + as: 'replier', + attributes: { exclude: ['password'] } }, { model: Tweet, - as: "tweetreply", + as: 'tweetreply', include: [ { model: User, - as: "author", - attributes: ["account", "name"], + as: 'author', + attributes: ['account', 'name'] // where: { role: "user" }, - }, - ], - }, + } + ] + } ], - order: [["createdAt", "DESC"]], - nest: true, + order: [['createdAt', 'DESC']], + nest: true }), Like.findAll({ - where: { userId }, - }), - ]); + where: { userId } + }) + ]) - const userRepliesResult = replies.map((reply) => ({ + const userRepliesResult = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, replierId: reply.replier.id, @@ -180,76 +180,76 @@ const userController = { createdAt: reply.createdAt, tweetId: reply.TweetId, tweetBelongerName: reply.tweetreply.author.name, - tweetBelongerAccount: reply.tweetreply.author.account, - })); + tweetBelongerAccount: reply.tweetreply.author.account + })) - res.status(200).json(userRepliesResult); + res.status(200).json(userRepliesResult) } catch (err) { - next(err); + next(err) } }, updateUser: async (req, res, next) => { try { - const { id } = req.params; - const { account, name, email, password, introduction } = req.body; + const { id } = req.params + const { account, name, email, password, introduction } = req.body - const user = await User.findByPk(id); + const user = await User.findByPk(id) if (!user) { return res.status(401).json({ - status: "error", - message: "This user does not exist", - }); + status: 'error', + message: 'This user does not exist' + }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id if (!currentUserId) { - throw new Error("Current user ID is missing"); + throw new Error('Current user ID is missing') } if (currentUserId !== Number(id)) { - throw new Error("Cannot edit other users profile"); + throw new Error('Cannot edit other users profile') } if (name && name.length > 50) { - throw new Error("the length of name should less than 50 characters"); + throw new Error('the length of name should less than 50 characters') } if (introduction && introduction.length > 160) { throw new Error( - "the length of introduction should less than 160 characters" - ); + 'the length of introduction should less than 160 characters' + ) } if (account) { const userByAccount = await User.findOne({ where: { account }, raw: true, - nest: true, - }); + nest: true + }) if (userByAccount && userByAccount.account === account) { - throw new Error("account 已重複註冊!"); + throw new Error('account 已重複註冊!') } } if (email) { - const userByEmail = await User.findOne({ where: { email } }); + const userByEmail = await User.findOne({ where: { email } }) if (userByEmail && userByEmail.email === email) { - throw new Error("email 已重複註冊!"); + throw new Error('email 已重複註冊!') } } - const { files } = req; + const { files } = req - let newAvatar = ""; - let newCover = ""; + let newAvatar = '' + let newCover = '' - if (files && files.avatar && files.avatar[0].fieldname === "avatar") { - newAvatar = await imgurFileHandler(files.avatar[0]); + if (files && files.avatar && files.avatar[0].fieldname === 'avatar') { + newAvatar = await imgurFileHandler(files.avatar[0]) } - if (files && files.cover && files.cover[0].fieldname === "cover") { - newCover = await imgurFileHandler(files.cover[0]); + if (files && files.cover && files.cover[0].fieldname === 'cover') { + newCover = await imgurFileHandler(files.cover[0]) } await user.update({ @@ -259,23 +259,23 @@ const userController = { password: password ? bcrypt.hashSync(password, 10) : user.password, introduction: introduction || user.introduction, avatar: newAvatar || user.avatar, - cover: newCover || user.cover, - }); + cover: newCover || user.cover + }) res.status(200).json({ - status: "success", - message: "Successfully update user.", - data: user, - }); + status: 'success', + message: 'Successfully update user.', + data: user + }) } catch (err) { - next(err); + next(err) } }, getUserLikes: async (req, res, next) => { try { - const currentUserId = helpers.getUser(req).id; - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const currentUserId = helpers.getUser(req).id + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const likes = await Like.findAll({ where: { userId: id }, raw: true, @@ -287,46 +287,46 @@ const userController = { // }, { model: Tweet, - as: "likedTweet", + as: 'likedTweet', attributes: [ - "id", - "UserId", - "description", - "createdAt", - "updatedAt", + 'id', + 'UserId', + 'description', + 'createdAt', + 'updatedAt', [ sequelize.literal( - "(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)" + '(SELECT COUNT(DISTINCT id) FROM Replies WHERE tweet_id = likedTweet.id)' ), - "replyCount", + 'replyCount' ], [ sequelize.literal( - "(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)" + '(SELECT COUNT(DISTINCT id) FROM Likes WHERE tweet_id = likedTweet.id)' ), - "likeCount", + 'likeCount' ], [ sequelize.literal( `(CASE WHEN EXISTS (SELECT 1 FROM Likes WHERE tweet_id = likedTweet.id AND user_id = ${currentUserId}) THEN TRUE ELSE FALSE END)` ), - "isLiked", - ], + 'isLiked' + ] ], include: [ - { model: User, as: "author" }, + { model: User, as: 'author' } // { model: Reply, as: "replies" }, - ], - }, - ], - }); - console.log(likes); + ] + } + ] + }) + console.log(likes) if (likes.length === 0) { - return res.status(200).json({ status: "success", message: "No likes" }); + return res.status(200).json({ status: 'success', message: 'No likes' }) } - const likedTweetsData = likes.map((like) => ({ + const likedTweetsData = likes.map(like => ({ TweetId: like.likedTweet.id, tweetBelongerName: like.likedTweet.author.name, tweetBelongerAccount: like.likedTweet.author.account, @@ -335,34 +335,34 @@ const userController = { createdAt: like.likedTweet.createdAt, replyCount: like.likedTweet.replyCount, likeCount: like.likedTweet.likeCount, - isLiked: like.likedTweet.isLiked === 1, - })); - res.status(200).json(likedTweetsData); + isLiked: like.likedTweet.isLiked === 1 + })) + res.status(200).json(likedTweetsData) } catch (err) { - next(err); + next(err) } }, getUserTweets: async (req, res, next) => { try { - const { id } = req.params; - const user = await User.findByPk(id, { raw: true, nest: true }); - if (!user) throw new Error("User does not exist"); + const { id } = req.params + const user = await User.findByPk(id, { raw: true, nest: true }) + if (!user) throw new Error('User does not exist') const [userTweets] = await Promise.all([ Tweet.findAll({ where: { userId: id }, - order: [["createdAt", "DESC"]], + order: [['createdAt', 'DESC']], attributes: [ - "id", - "description", - "createdAt", - "updatedAt", + 'id', + 'description', + 'createdAt', + 'updatedAt', [ sequelize.literal(`( SELECT COUNT(*) FROM Likes WHERE Likes.tweet_id = Tweet.id )`), - "likeCount", + 'likeCount' ], [ sequelize.literal(`( @@ -370,20 +370,20 @@ const userController = { FROM Replies WHERE Replies.tweet_id = Tweet.id )`), - "replyCount", - ], + 'replyCount' + ] ], include: [ { model: User, - as: "author", - attributes: { exclude: ["password"] }, - }, - ], - }), - ]); - console.log(userTweets); - const userTweetsData = userTweets.map((tweet) => ({ + as: 'author', + attributes: { exclude: ['password'] } + } + ] + }) + ]) + console.log(userTweets) + const userTweetsData = userTweets.map(tweet => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, tweetBelongerAccount: tweet.author.account, @@ -391,97 +391,97 @@ const userController = { description: tweet.description, createdAt: tweet.createdAt, replyCount: tweet.replyCount, - likeCount: tweet.likeCount, - })); + likeCount: tweet.likeCount + })) - res.status(200).json(userTweetsData); + res.status(200).json(userTweetsData) } catch (err) { - next(err); + next(err) } }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params; // 18 target + const { id } = req.params // 18 target const user = await User.findByPk(id, { include: { model: User, - as: "Followers", - }, - }); + as: 'Followers' + } + }) - if (!user) throw new Error("User does not exist"); + if (!user) throw new Error('User does not exist') if (!user.Followers) { return res .status(200) - .json({ status: "success", message: "No followers" }); + .json({ status: 'success', message: 'No followers' }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) const followingIds = currentUserFollowingId.map( - (item) => item.followingId - ); + item => item.followingId + ) - const followersData = user.Followers.map((follower) => ({ + const followersData = user.Followers.map(follower => ({ followerId: follower.id, followerAccount: follower.account, followerName: follower.name, followerAvatar: follower.avatar, isFollowed: followingIds.includes(follower.id), - follower, - })); + follower + })) - res.status(200).json(followersData); + res.status(200).json(followersData) } catch (err) { - next(err); + next(err) } }, getUserFollowings: async (req, res, next) => { try { - const { id } = req.params; + const { id } = req.params const user = await User.findByPk(id, { include: { model: User, - as: "Followings", - }, - }); - if (!user) throw new Error("User does not exist"); + as: 'Followings' + } + }) + if (!user) throw new Error('User does not exist') if (!user.Followings) { return res .status(200) - .json({ status: "success", message: "No followings" }); + .json({ status: 'success', message: 'No followings' }) } - const currentUserId = helpers.getUser(req).id; + const currentUserId = helpers.getUser(req).id const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - }); + raw: true + }) const followingIds = currentUserFollowingId.map( - (item) => item.followingId - ); + item => item.followingId + ) - const followingsData = user.Followings.map((following) => ({ + const followingsData = user.Followings.map(following => ({ followingId: following.id, followingAccount: following.account, followingName: following.name, followingAvatar: following.avatar, isFollowed: followingIds.includes(following.id), - following, - })); + following + })) - res.status(200).json(followingsData); + res.status(200).json(followingsData) } catch (err) { - next(err); + next(err) } - }, -}; + } +} -module.exports = userController; +module.exports = userController diff --git a/models/index.js b/models/index.js index e92dffac8b..97d2de576d 100644 --- a/models/index.js +++ b/models/index.js @@ -7,21 +7,30 @@ const basename = path.basename(__filename) const env = process.env.NODE_ENV || 'development' const config = require(__dirname + '/../config/config.json')[env] const db = {} - +console.log(env) let sequelize if (config.use_env_variable) { sequelize = new Sequelize(process.env[config.use_env_variable], config) } else { - sequelize = new Sequelize(config.database, config.username, config.password, config) + sequelize = new Sequelize( + config.database, + config.username, + config.password, + config + ) } -fs - .readdirSync(__dirname) +fs.readdirSync(__dirname) .filter(file => { - return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js') + return ( + file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js' + ) }) .forEach(file => { - const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes) + const model = require(path.join(__dirname, file))( + sequelize, + Sequelize.DataTypes + ) db[model.name] = model }) diff --git a/package.json b/package.json index 7c8ccb5f96..17d91bfbaa 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "start": "NODE_ENV=development node app.js", "dev": "NODE_ENV=development nodemon app.js", "lint": "eslint \"**/*.js\" --fix", - "test": "mocha test --exit --recursive --timeout 5000" + "test": "NODE_ENV=test mocha test --exit --recursive --timeout 5000" }, "engines": { "node": "18.15.0" From 5bf112daccb80d334bdd074c46665bda24c89c21 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sat, 2 Sep 2023 15:56:03 +0800 Subject: [PATCH 148/170] fix: bugs --- config/config.json | 1 - controllers/apis/user-controller.js | 55 ++++++++++++----------------- 2 files changed, 23 insertions(+), 33 deletions(-) diff --git a/config/config.json b/config/config.json index 8b6bde1566..5e4a51b957 100644 --- a/config/config.json +++ b/config/config.json @@ -31,4 +31,3 @@ "dialect": "mysql" } } - diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 35adabc6cc..d73934927c 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -8,7 +8,6 @@ const helpers = require('../../_helpers') const { User, Tweet, Reply, Followship, Like } = db const { Op } = require('sequelize') -const like = require('../../models/like') const userController = { signUp: async (req, res, next) => { @@ -138,37 +137,29 @@ const userController = { getUserRepliedTweets: async (req, res, next) => { try { const userId = req.params.id - - const [user, replies] = await Promise.all([ - User.findByPk(userId, { raw: true, nest: true }), - Reply.findAll({ - where: { UserId: userId }, - include: [ - { - model: User, - as: 'replier', - attributes: { exclude: ['password'] } - }, - { - model: Tweet, - as: 'tweetreply', - include: [ - { - model: User, - as: 'author', - attributes: ['account', 'name'] - // where: { role: "user" }, - } - ] - } - ], - order: [['createdAt', 'DESC']], - nest: true - }), - Like.findAll({ - where: { userId } - }) - ]) + const replies = await Reply.findAll({ + where: { UserId: userId }, + include: [ + { + model: User, + as: 'replier', + attributes: { exclude: ['password'] } + }, + { + model: Tweet, + as: 'tweetreply', + include: [ + { + model: User, + as: 'author', + attributes: ['account', 'name'] + } + ] + } + ], + order: [['createdAt', 'DESC']], + nest: true + }) const userRepliesResult = replies.map(reply => ({ replyId: reply.id, From d63f07293d1024a8b954a698520b710fb7b511ad Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sat, 2 Sep 2023 16:01:09 +0800 Subject: [PATCH 149/170] fix: update putUser --- controllers/apis/user-controller.js | 47 +++++++++-------------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 35adabc6cc..38cbe71779 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -192,25 +192,27 @@ const userController = { try { const { id } = req.params const { account, name, email, password, introduction } = req.body - - const user = await User.findByPk(id) - - if (!user) { - return res.status(401).json({ + const currentUserId = helpers.getUser(req).id + if (!id === currentUserId) { + return res.status(403).json({ status: 'error', - message: 'This user does not exist' + message: 'You are not allowed to edit other users' }) } - const currentUserId = helpers.getUser(req).id + const findUser = await User.findAll({ + where: { id: { [Op.ne]: id } } + }) - if (!currentUserId) { - throw new Error('Current user ID is missing') - } + const userByAccount = findUser.find(user => user.account === account) + const userByEmail = findUser.find(user => user.email === email) - if (currentUserId !== Number(id)) { - throw new Error('Cannot edit other users profile') - } + if (userByAccount) return res.status(400).json({ status: 'error', message: 'account 已重複註冊!' }) + if (userByEmail) return res.status(400).json({ status: 'error', message: 'email 已重複註冊!' }) + + const user = await User.findByPk(id) + + if (!user) return res.status(400).json({ status: 'error', message: 'User does not exist' }) if (name && name.length > 50) { throw new Error('the length of name should less than 50 characters') @@ -221,25 +223,6 @@ const userController = { ) } - if (account) { - const userByAccount = await User.findOne({ - where: { account }, - raw: true, - nest: true - }) - - if (userByAccount && userByAccount.account === account) { - throw new Error('account 已重複註冊!') - } - } - - if (email) { - const userByEmail = await User.findOne({ where: { email } }) - if (userByEmail && userByEmail.email === email) { - throw new Error('email 已重複註冊!') - } - } - const { files } = req let newAvatar = '' From b84b0bb320bd08914353e4e1dd3a9fc6fc51cfe1 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sun, 3 Sep 2023 20:47:45 +0800 Subject: [PATCH 150/170] fix: to meet dod --- seeders/20230821074916-tweets-seed-file.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seeders/20230821074916-tweets-seed-file.js b/seeders/20230821074916-tweets-seed-file.js index 8985cf2133..791e733651 100644 --- a/seeders/20230821074916-tweets-seed-file.js +++ b/seeders/20230821074916-tweets-seed-file.js @@ -12,7 +12,7 @@ module.exports = { attributes: ['id'] }) Array.from({ length: 10 }).map((el, i) => { - for (let j = 0; j < 5; ++j) { + for (let i = 0; i < 10; ++i) { data.push({ description: faker.lorem.text(140), created_at: new Date(), From 4e4ba590c2cc24d35aa6aec63db578a5c68d44fa Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Sun, 3 Sep 2023 20:48:20 +0800 Subject: [PATCH 151/170] fix: to meet dod --- controllers/apis/admin-controller.js | 3 +-- controllers/apis/followship-controller.js | 4 +++- controllers/apis/tweet-controller.js | 7 ++++--- controllers/apis/user-controller.js | 9 +++++---- models/index.js | 2 +- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 9e78236218..3ea8ccfbfe 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -44,14 +44,13 @@ const adminController = { order: [[sequelize.col('tweetCount'), 'DESC'], ['createdAt']] } const users = await User.findAll(options) - // console.log("usersbeforeforeach", users); + users.forEach(user => { if (user.introduction) { user.introduction = user.introduction.substring(0, 50) } }) - // console.log(users); res.status(200).json(users) } catch (error) { next(error) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index a20b95146c..9a7618100b 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -11,6 +11,7 @@ const followshipController = { const userId = getUser.id const user = await User.findByPk(userId) if (!user) throw new Error("User didn't exist!") + if (user.id === followingId) throw new Error('不能追蹤自己!') const followship = await Followship.findOrCreate({ raw: true, nest: true, @@ -25,7 +26,7 @@ const followshipController = { if (!followship[1]) { throw new Error("You've are already followed this user!") } - console.log(followship) + res.status(200).json({ status: 'success', message: 'successfully follow user!' @@ -41,6 +42,7 @@ const followshipController = { const userId = getUser.id // 現在使用者本人 const user = await User.findByPk(userId) if (!user) throw new Error("User didn't exist!") + const followship = await Followship.destroy({ where: { followerId: userId, diff --git a/controllers/apis/tweet-controller.js b/controllers/apis/tweet-controller.js index ea869b1f2a..3d0cabd168 100644 --- a/controllers/apis/tweet-controller.js +++ b/controllers/apis/tweet-controller.js @@ -209,7 +209,7 @@ const tweetContorller = { }) if (!replies) throw new Error('This tweet has no replies') - console.log(replies) + const repliesData = replies.map(reply => ({ replyId: reply.id, comment: reply.comment, @@ -265,7 +265,7 @@ const tweetContorller = { } }) ]) - console.log(reply, currentUser, tweet) + const replyData = { id: reply.dataValues.id, tweetId, @@ -278,7 +278,7 @@ const tweetContorller = { createdAt, updatedAt } - console.log(replyData) + res.status(200).json({ status: 'success', message: 'successfully created reply', @@ -299,6 +299,7 @@ const tweetContorller = { }, nest: true, raw: true, + order: [['createdAt', 'DESC']], include: [ { model: User, diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index d5f151f873..e1d651b94e 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -128,7 +128,7 @@ const userController = { follow => follow.followingId === Number(id) ) } - console.log(user) + res.status(200).json(user) } catch (err) { next(err) @@ -252,6 +252,7 @@ const userController = { if (!user) throw new Error('User does not exist') const likes = await Like.findAll({ where: { userId: id }, + order: [['createdAt', 'DESC']], raw: true, nest: true, include: [ @@ -294,7 +295,7 @@ const userController = { } ] }) - console.log(likes) + if (likes.length === 0) { return res.status(200).json({ status: 'success', message: 'No likes' }) @@ -356,7 +357,7 @@ const userController = { ] }) ]) - console.log(userTweets) + const userTweetsData = userTweets.map(tweet => ({ TweetId: tweet.id, tweetBelongerName: tweet.author.name, @@ -375,7 +376,7 @@ const userController = { }, getUserFollowers: async (req, res, next) => { try { - const { id } = req.params // 18 target + const { id } = req.params const user = await User.findByPk(id, { include: { model: User, diff --git a/models/index.js b/models/index.js index 97d2de576d..4beb4a38af 100644 --- a/models/index.js +++ b/models/index.js @@ -7,7 +7,7 @@ const basename = path.basename(__filename) const env = process.env.NODE_ENV || 'development' const config = require(__dirname + '/../config/config.json')[env] const db = {} -console.log(env) + let sequelize if (config.use_env_variable) { sequelize = new Sequelize(process.env[config.use_env_variable], config) From 3108e93e07a3d329747c21135faa2c3ae710b7ad Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 3 Sep 2023 22:51:42 +0800 Subject: [PATCH 152/170] fix: followingId error --- controllers/apis/followship-controller.js | 2 +- controllers/apis/user-controller.js | 21 ++++++++++++++++----- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/controllers/apis/followship-controller.js b/controllers/apis/followship-controller.js index 9a7618100b..7dc888be49 100644 --- a/controllers/apis/followship-controller.js +++ b/controllers/apis/followship-controller.js @@ -42,7 +42,7 @@ const followshipController = { const userId = getUser.id // 現在使用者本人 const user = await User.findByPk(userId) if (!user) throw new Error("User didn't exist!") - + const followship = await Followship.destroy({ where: { followerId: userId, diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index e1d651b94e..ba6f71eac2 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -121,7 +121,7 @@ const userController = { if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ - where: { followerId: currentUserId }, + where: { followingId: currentUserId }, raw: true }) user.isFollowed = checkUserFollowing.some( @@ -198,12 +198,24 @@ const userController = { const userByAccount = findUser.find(user => user.account === account) const userByEmail = findUser.find(user => user.email === email) - if (userByAccount) return res.status(400).json({ status: 'error', message: 'account 已重複註冊!' }) - if (userByEmail) return res.status(400).json({ status: 'error', message: 'email 已重複註冊!' }) + if (userByAccount) { + return res + .status(400) + .json({ status: 'error', message: 'account 已重複註冊!' }) + } + if (userByEmail) { + return res + .status(400) + .json({ status: 'error', message: 'email 已重複註冊!' }) + } const user = await User.findByPk(id) - if (!user) return res.status(400).json({ status: 'error', message: 'User does not exist' }) + if (!user) { + return res + .status(400) + .json({ status: 'error', message: 'User does not exist' }) + } if (name && name.length > 50) { throw new Error('the length of name should less than 50 characters') @@ -296,7 +308,6 @@ const userController = { ] }) - if (likes.length === 0) { return res.status(200).json({ status: 'success', message: 'No likes' }) } From 2a3c4ee8974615511fa07529f4046609826c14d8 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 3 Sep 2023 22:58:44 +0800 Subject: [PATCH 153/170] fix : bugs --- controllers/apis/user-controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index ba6f71eac2..a35b52d985 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -94,7 +94,7 @@ const userController = { const { id } = req.params const currentUserId = helpers.getUser(req).id - const [user, tweetCount, followerCount, followingCount] = + const [user, tweetCount, followingCount, followerCount] = await Promise.all([ User.findByPk(id, { raw: true, nest: true }), Tweet.count({ @@ -121,7 +121,7 @@ const userController = { if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ - where: { followingId: currentUserId }, + where: { follerId: currentUserId }, raw: true }) user.isFollowed = checkUserFollowing.some( From 43d041f3f54c5b52d1cb6649b11b82c896d6edbe Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Sun, 3 Sep 2023 23:15:34 +0800 Subject: [PATCH 154/170] fix :typo --- controllers/apis/user-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index a35b52d985..ba40eef914 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -121,7 +121,7 @@ const userController = { if (Number(id) !== currentUserId) { const checkUserFollowing = await Followship.findAll({ - where: { follerId: currentUserId }, + where: { followerId: currentUserId }, raw: true }) user.isFollowed = checkUserFollowing.some( From d52ed05a2debdea903cd528dba5cd2e6cfcdbe73 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Mon, 4 Sep 2023 01:12:21 +0800 Subject: [PATCH 155/170] fix: to meet userstory --- controllers/apis/admin-controller.js | 2 +- controllers/apis/user-controller.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/apis/admin-controller.js b/controllers/apis/admin-controller.js index 3ea8ccfbfe..bbc27cceeb 100644 --- a/controllers/apis/admin-controller.js +++ b/controllers/apis/admin-controller.js @@ -123,7 +123,7 @@ const adminController = { const user = await User.findOne({ where: { account } }) if (!user) throw new Error('User does not exist') - if (user.role === 'user') throw new Error('user permission denied') + if (user.role === 'user') throw new Error('帳號不存在') if (!bcrypt.compareSync(password, user.password)) { throw new Error('Incorrect password') } diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index ba40eef914..dbdb890e89 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -64,7 +64,7 @@ const userController = { const user = await User.findOne({ where: { account } }) if (!user) throw new Error('User does not exist') - if (user.role === 'admin') throw new Error('admin permission denied') + if (user.role === 'admin') throw new Error('帳號不存在') if (!bcrypt.compareSync(password, user.password)) { throw new Error('Incorrect password') } From 2e6c13680380901ccd0c98ba3d87e731b8836318 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 4 Sep 2023 10:57:56 +0800 Subject: [PATCH 156/170] fix: follow order --- controllers/apis/user-controller.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index dbdb890e89..3c1d90a32e 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -406,7 +406,8 @@ const userController = { const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true + raw: true, + order: [['createdAt', 'DESC']] }) const followingIds = currentUserFollowingId.map( @@ -446,6 +447,7 @@ const userController = { const currentUserId = helpers.getUser(req).id const currentUserFollowingId = await Followship.findAll({ + order: [['createdAt', 'DESC']], where: { followerId: currentUserId }, raw: true }) From 0d60f72ccd264ed91c2560a122fb41878c91a374 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 4 Sep 2023 11:18:24 +0800 Subject: [PATCH 157/170] fix: order --- controllers/apis/user-controller.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 3c1d90a32e..a025a45690 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -391,7 +391,8 @@ const userController = { const user = await User.findByPk(id, { include: { model: User, - as: 'Followers' + as: 'Followers', + order: [['createdAt', 'DESC']] } }) @@ -406,8 +407,8 @@ const userController = { const currentUserFollowingId = await Followship.findAll({ where: { followerId: currentUserId }, - raw: true, - order: [['createdAt', 'DESC']] + raw: true + // order: [['createdAt', 'DESC']] }) const followingIds = currentUserFollowingId.map( @@ -434,7 +435,8 @@ const userController = { const user = await User.findByPk(id, { include: { model: User, - as: 'Followings' + as: 'Followings', + order: [['createdAt', 'DESC']] } }) if (!user) throw new Error('User does not exist') @@ -447,7 +449,7 @@ const userController = { const currentUserId = helpers.getUser(req).id const currentUserFollowingId = await Followship.findAll({ - order: [['createdAt', 'DESC']], + // order: [['createdAt', 'DESC']], where: { followerId: currentUserId }, raw: true }) From bd00c20fc5cbf7513e1877a037726bb6afe32819 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 4 Sep 2023 11:35:14 +0800 Subject: [PATCH 158/170] fix:bugs --- controllers/apis/user-controller.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index a025a45690..c21287e024 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -392,7 +392,15 @@ const userController = { include: { model: User, as: 'Followers', - order: [['createdAt', 'DESC']] + through: { attributes: ['createdAt'] }, + order: [ + [ + { model: User, as: 'Followers' }, + 'Followship', + 'createdAt', + 'DESC' + ] + ] } }) @@ -436,7 +444,15 @@ const userController = { include: { model: User, as: 'Followings', - order: [['createdAt', 'DESC']] + through: { attributes: ['createdAt'] }, + order: [ + [ + { model: User, as: 'Followings' }, + 'Followship', + 'createdAt', + 'DESC' + ] + ] } }) if (!user) throw new Error('User does not exist') From 180dbad0fecdecaf38083baae40fd946d395830c Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 4 Sep 2023 11:39:22 +0800 Subject: [PATCH 159/170] fix :Bugs --- controllers/apis/user-controller.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index c21287e024..3d7b127a16 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -393,14 +393,15 @@ const userController = { model: User, as: 'Followers', through: { attributes: ['createdAt'] }, - order: [ - [ - { model: User, as: 'Followers' }, - 'Followship', - 'createdAt', - 'DESC' - ] - ] + order: [{ model: Followship, as: 'follower' }, 'createdAt', 'DESC'] + // order: [ + // [ + // { model: User, as: "Followers" }, + // "Followship", + // "createdAt", + // "DESC", + // ], + // ], } }) From e378d8c409b2797cb92b7d03a7296b820e30534b Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 4 Sep 2023 11:49:47 +0800 Subject: [PATCH 160/170] fix: bugs --- controllers/apis/user-controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/apis/user-controller.js b/controllers/apis/user-controller.js index 3d7b127a16..6c7b81023f 100644 --- a/controllers/apis/user-controller.js +++ b/controllers/apis/user-controller.js @@ -392,7 +392,7 @@ const userController = { include: { model: User, as: 'Followers', - through: { attributes: ['createdAt'] }, + // through: { attributes: ['createdAt'] }, order: [{ model: Followship, as: 'follower' }, 'createdAt', 'DESC'] // order: [ // [ @@ -445,7 +445,7 @@ const userController = { include: { model: User, as: 'Followings', - through: { attributes: ['createdAt'] }, + // through: { attributes: ['createdAt'] }, order: [ [ { model: User, as: 'Followings' }, From 6ca7ce3b79334071a5b81576b3af200266c60c3d Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 4 Sep 2023 15:37:02 +0800 Subject: [PATCH 161/170] fix: delete package lock --- package-lock.json | 6765 --------------------------------------------- 1 file changed, 6765 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 758c5471f2..0000000000 --- a/package-lock.json +++ /dev/null @@ -1,6765 +0,0 @@ -{ - "name": "test", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "test", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "bcrypt": "^5.1.1", - "bcrypt-nodejs": "0.0.3", - "bcryptjs": "^2.4.3", - "body-parser": "^1.20.2", - "chai": "^4.2.0", - "connect-flash": "^0.1.1", - "cors": "^2.8.5", - "dotenv": "^16.3.1", - "express": "^4.16.4", - "express-session": "^1.17.3", - "faker": "^5.5.3", - "imgur": "^1.0.2", - "jsonwebtoken": "^8.5.1", - "method-override": "^3.0.0", - "mocha": "^6.0.2", - "multer": "^1.4.3", - "mysql2": "^2.3.0", - "passport": "^0.4.0", - "passport-jwt": "^4.0.1", - "passport-local": "^1.0.0", - "sequelize": "^6.6.5", - "sequelize-cli": "^6.2.0", - "sinon": "^10.0.0", - "sinon-chai": "^3.3.0" - }, - "devDependencies": { - "eslint-config-standard": "^17.1.0", - "proxyquire": "^2.1.3", - "sequelize-test-helpers": "^1.4.2", - "standard": "*", - "supertest": "^3.3.0" - }, - "engines": { - "node": "18.15.0" - } - }, - "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_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.7.0.tgz", - "integrity": "sha512-+HencqxU7CFJnQb7IKtuNBqS6Yx3Tz4kOL8BJXo+JyeiBm5MEX6pO8onXDkjrkCRlfYXS1Axro15ZjVFe9YgsA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@eslint/js": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", - "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", - "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "dependencies": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@one-ini/wasm": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", - "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", - "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==" - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "node_modules/@types/debug": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" - }, - "node_modules/@types/node": { - "version": "20.5.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.2.tgz", - "integrity": "sha512-5j/lXt7unfPOUlrKC34HIaedONleyLtwkKggiD/0uuMfT8gg2EOpg0dz4lCD15Ga7muC+1WzJZAjIB9simWd6Q==" - }, - "node_modules/@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/validator": { - "version": "13.11.1", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", - "integrity": "sha512-d/MUkJYdOeKycmm75Arql4M5+UuXmf4cHdHKsyw1GcvnNgL6s77UkgSgJ8TE/rI5PYsnwYq5jkcWBLuN/MpQ1A==" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" - }, - "node_modules/aproba": { - "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==" - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz", - "integrity": "sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.reduce": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", - "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", - "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "engines": { - "node": "*" - } - }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/bcrypt": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", - "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", - "hasInstallScript": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.11", - "node-addon-api": "^5.0.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/bcrypt-nodejs": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", - "integrity": "sha512-NmTbLm867btBHCBZ222FQXkQKzecB0KG6pTXFa6NeTVZaSnLfCsx7EK2PL3J+kX8xJThUquEBbhimRCKKZX9zA==", - "deprecated": "bcrypt-nodejs is no longer actively maintained. Please use bcrypt or bcryptjs. See https://github.com/kelektiv/node.bcrypt.js/wiki/bcrypt-vs-brypt.js to learn more about these two options" - }, - "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "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/busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==", - "dependencies": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/busboy/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/busboy/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/busboy/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/chai": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^4.1.2", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", - "engines": { - "node": "*" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/cli-color": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", - "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.61", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.15", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "engines": { - "node": ">=14" - } - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concat-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/concat-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/concat-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/connect-flash": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", - "integrity": "sha512-2rcfELQt/ZMP+SM/pG8PyhJRaLKp+6Hk2IUBNkEit09X+vwn3QsAL3ZbYtxUn7NVPzbMTSLRDhqe0B/eh30RYA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/cookiejar": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", - "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==", - "dependencies": { - "readable-stream": "1.1.x", - "streamsearch": "0.1.2" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/dicer/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/dicer/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/dicer/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, - "node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "engines": { - "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/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/dottie": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", - "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/editorconfig": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", - "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", - "dependencies": { - "@one-ini/wasm": "0.1.1", - "commander": "^10.0.0", - "minimatch": "9.0.1", - "semver": "^7.5.3" - }, - "bin": { - "editorconfig": "bin/editorconfig" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/editorconfig/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==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/editorconfig/node_modules/minimatch": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", - "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", - "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.1", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-array-concat": "^1.0.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.13.tgz", - "integrity": "sha512-LK3VGwzvaPWobO8xzXXGRUOGw8Dcjyfk62CsY/wfHN75CwsJPbuypOYJxK6g5RyEL8YDjIWcl6jgd8foO6mmrA==", - "dev": true, - "dependencies": { - "asynciterator.prototype": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.21.3", - "es-set-tostringtag": "^2.0.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.2.1", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "iterator.prototype": "^1.1.0", - "safe-array-concat": "^1.0.0" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", - "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "^8.47.0", - "@humanwhocodes/config-array": "^0.11.10", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "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", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "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", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", - "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0" - } - }, - "node_modules/eslint-config-standard-jsx": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-11.0.0.tgz", - "integrity": "sha512-+1EV/R0JxEK1L0NGolAr8Iktm3Rgotx3BKwgaX+eAuSX8D952LULKtjgZD3F+e6SvibONnhLwoTi9DPxN5LvvQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peerDependencies": { - "eslint": "^8.8.0", - "eslint-plugin-react": "^7.28.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/eslint-plugin-es": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", - "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", - "dev": true, - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-es-x": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.2.0.tgz", - "integrity": "sha512-9dvv5CcvNjSJPqnS5uZkqb3xmbeqRLnvXKK7iI5+oK/yTusyc46zbBZKENGsOfojm/mKfszyZb+wNqNPAPeGXA==", - "dev": true, - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.6.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ota-meshi" - }, - "peerDependencies": { - "eslint": ">=8" - } - }, - "node_modules/eslint-plugin-es/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-plugin-es/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-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", - "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/eslint-plugin-import/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_modules/eslint-plugin-n": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.0.2.tgz", - "integrity": "sha512-Y66uDfUNbBzypsr0kELWrIz+5skicECrLUqlWuXawNSLUq3ltGlCwu6phboYYOTSnoTdHgTLrc+5Ydo6KjzZog==", - "dev": true, - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.1.0", - "ignore": "^5.2.4", - "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-promise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz", - "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.33.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", - "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.12", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.8" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", - "dev": true, - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/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_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==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "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/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express-session": { - "version": "1.17.3", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", - "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", - "dependencies": { - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/express-session/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/faker": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", - "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "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==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-keys": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==", - "dev": true, - "dependencies": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dependencies": { - "is-buffer": "~2.0.3" - }, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/formidable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", - "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", - "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", - "dev": true, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dependencies": { - "is-property": "^1.0.2" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "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/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "engines": { - "node": ">=4.x" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/imgur": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/imgur/-/imgur-1.0.2.tgz", - "integrity": "sha512-bZJkRpa3ReR7lSEzAOjO4PPl9OIDQPuiKoG2aOh36PrTBQCrZL/oTcc6VClyyXEg9O6rEMpsuCloxfhqybpfZA==", - "dependencies": { - "commander": "^7.1.0", - "form-data": "^4.0.0", - "got": "^11.8.1" - }, - "bin": { - "imgur": "cli.js" - } - }, - "node_modules/imgur/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/imgur/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflection": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", - "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", - "engines": [ - "node >= 0.4.0" - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "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", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", - "dependencies": { - "which-typed-array": "^1.1.11" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/iterator.prototype": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.0.tgz", - "integrity": "sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "has-tostringtag": "^1.0.0", - "reflect.getprototypeof": "^1.0.3" - } - }, - "node_modules/js-beautify": { - "version": "1.14.9", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz", - "integrity": "sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==", - "dependencies": { - "config-chain": "^1.1.13", - "editorconfig": "^1.0.3", - "glob": "^8.1.0", - "nopt": "^6.0.0" - }, - "bin": { - "css-beautify": "js/bin/css-beautify.js", - "html-beautify": "js/bin/html-beautify.js", - "js-beautify": "js/bin/js-beautify.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/js-beautify/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==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/js-beautify/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "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/js-beautify/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/js-beautify/node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=4", - "npm": ">=1.4.28" - } - }, - "node_modules/jsonwebtoken/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/jsonwebtoken/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/load-json-file": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/load-json-file/node_modules/type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, - "node_modules/log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dependencies": { - "chalk": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/log-symbols/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "engines": { - "node": ">=8" - } - }, - "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/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dependencies": { - "es5-ext": "~0.10.2" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "node_modules/method-override": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", - "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", - "dependencies": { - "debug": "3.1.0", - "methods": "~1.1.2", - "parseurl": "~1.3.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/method-override/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", - "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mocha": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz", - "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==", - "dependencies": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "2.2.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.4", - "ms": "2.1.1", - "node-environment-flags": "1.0.5", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "node_modules/mocha/node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mocha/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/module-not-found-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==", - "dev": true - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.43", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", - "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", - "dependencies": { - "moment": "^2.29.4" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/multer": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", - "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", - "deprecated": "Multer 1.x is affected by CVE-2022-24434. This is fixed in v1.4.4-lts.1 which drops support for versions of Node.js before 6. Please upgrade to at least Node.js 6 and version 1.4.4-lts.1 of Multer. If you need support for older versions of Node.js, we are open to accepting patches that would fix the CVE on the main 1.x release line, whilst maintaining compatibility with Node.js 0.10.", - "dependencies": { - "append-field": "^1.0.0", - "busboy": "^0.2.11", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.4", - "object-assign": "^4.1.1", - "on-finished": "^2.3.0", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/mysql2": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", - "integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==", - "dependencies": { - "denque": "^2.0.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.3", - "long": "^4.0.0", - "lru-cache": "^6.0.0", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/named-placeholders": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", - "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", - "dependencies": { - "lru-cache": "^7.14.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/named-placeholders/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, - "node_modules/nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", - "dependencies": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/nise/node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/node-addon-api": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", - "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" - }, - "node_modules/node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node_modules/node-environment-flags/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/node-fetch": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", - "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", - "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", - "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz", - "integrity": "sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==", - "dependencies": { - "array.prototype.reduce": "^1.0.5", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.21.2", - "safe-array-concat": "^1.0.0" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.0.tgz", - "integrity": "sha512-70MWG6NfRH9GnbZOikuhPPYzpUpof9iW2J9E4dW7FXTqPNb6rllE6u39SKwwiNh8lCwX3DDb5OgcKGiEBrTTyw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.21.2", - "get-intrinsic": "^1.2.1" - } - }, - "node_modules/object.hasown": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", - "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", - "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" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/passport": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", - "dependencies": { - "passport-strategy": "1.x.x", - "pause": "0.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-jwt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz", - "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==", - "dependencies": { - "jsonwebtoken": "^9.0.0", - "passport-strategy": "^1.0.0" - } - }, - "node_modules/passport-jwt/node_modules/jsonwebtoken": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", - "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", - "dependencies": { - "jws": "^3.2.2", - "lodash": "^4.17.21", - "ms": "^2.1.1", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/passport-jwt/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/passport-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", - "dependencies": { - "passport-strategy": "1.x.x" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "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==" - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "engines": { - "node": "*" - } - }, - "node_modules/pause": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" - }, - "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", - "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", - "dev": true, - "dependencies": { - "find-up": "^3.0.0", - "load-json-file": "^5.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-conf/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxyquire": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", - "dev": true, - "dependencies": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" - } - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.3.tgz", - "integrity": "sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.1", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" - }, - "node_modules/resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", - "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", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/retry-as-promised": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", - "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", - "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/seq-queue": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", - "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" - }, - "node_modules/sequelize": { - "version": "6.32.1", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.32.1.tgz", - "integrity": "sha512-3Iv0jruv57Y0YvcxQW7BE56O7DC1BojcfIrqh6my+IQwde+9u/YnuYHzK+8kmZLhLvaziRT1eWu38nh9yVwn/g==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/sequelize" - } - ], - "dependencies": { - "@types/debug": "^4.1.8", - "@types/validator": "^13.7.17", - "debug": "^4.3.4", - "dottie": "^2.0.4", - "inflection": "^1.13.4", - "lodash": "^4.17.21", - "moment": "^2.29.4", - "moment-timezone": "^0.5.43", - "pg-connection-string": "^2.6.0", - "retry-as-promised": "^7.0.4", - "semver": "^7.5.1", - "sequelize-pool": "^7.1.0", - "toposort-class": "^1.0.1", - "uuid": "^8.3.2", - "validator": "^13.9.0", - "wkx": "^0.5.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependenciesMeta": { - "ibm_db": { - "optional": true - }, - "mariadb": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "oracledb": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-hstore": { - "optional": true - }, - "snowflake-sdk": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "tedious": { - "optional": true - } - } - }, - "node_modules/sequelize-cli": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.6.1.tgz", - "integrity": "sha512-C3qRpy1twBsFa855qOQFSYWer8ngiaZP05/OAsT1QCUwtc6UxVNNiQ0CGUt98T9T1gi5D3TGWL6le8HWUKELyw==", - "dependencies": { - "cli-color": "^2.0.3", - "fs-extra": "^9.1.0", - "js-beautify": "^1.14.5", - "lodash": "^4.17.21", - "resolve": "^1.22.1", - "umzug": "^2.3.0", - "yargs": "^16.2.0" - }, - "bin": { - "sequelize": "lib/sequelize", - "sequelize-cli": "lib/sequelize" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/sequelize-cli/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/sequelize-cli/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/sequelize-cli/node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/sequelize-cli/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sequelize-cli/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" - } - }, - "node_modules/sequelize-pool": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", - "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/sequelize-test-helpers": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/sequelize-test-helpers/-/sequelize-test-helpers-1.4.3.tgz", - "integrity": "sha512-5NzQljzIDaKi+iAK5237DcemsJI1FmTPgMoE9Tu/oYZVwa6l3Lf5nF2yV0ruTrsrAKi2XWywnXFl2AATEfoBGw==", - "dev": true, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/davesag" - }, - "peerDependencies": { - "chai": ">= 4", - "sinon": ">= 10.0.0" - } - }, - "node_modules/sequelize/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/sequelize/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.1.0", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon-chai": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "peerDependencies": { - "chai": "^4.0.0", - "sinon": ">=4.0.0" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/sqlstring": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", - "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/standard/-/standard-17.1.0.tgz", - "integrity": "sha512-jaDqlNSzLtWYW4lvQmU0EnxWMUGQiwHasZl5ZEIwx3S/ijZDjZOzs1y1QqKwKs5vqnFpGtizo4NOYX2s0Voq/g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "eslint": "^8.41.0", - "eslint-config-standard": "17.1.0", - "eslint-config-standard-jsx": "^11.0.0", - "eslint-plugin-import": "^2.27.5", - "eslint-plugin-n": "^15.7.0", - "eslint-plugin-promise": "^6.1.1", - "eslint-plugin-react": "^7.32.2", - "standard-engine": "^15.0.0", - "version-guard": "^1.1.1" - }, - "bin": { - "standard": "bin/cmd.cjs" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/standard-engine": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-15.1.0.tgz", - "integrity": "sha512-VHysfoyxFu/ukT+9v49d4BRXIokFRZuH3z1VRxzFArZdjSCFpro6rEIU3ji7e4AoAtuSfKBkiOmsrDqKW5ZSRw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "get-stdin": "^8.0.0", - "minimist": "^1.2.6", - "pkg-conf": "^3.1.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/standard/node_modules/eslint-plugin-n": { - "version": "15.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz", - "integrity": "sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==", - "dev": true, - "dependencies": { - "builtins": "^5.0.1", - "eslint-plugin-es": "^4.1.0", - "eslint-utils": "^3.0.0", - "ignore": "^5.1.1", - "is-core-module": "^2.11.0", - "minimatch": "^3.1.2", - "resolve": "^1.22.1", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=12.22.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", - "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", - "dev": true, - "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/superagent/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "node_modules/superagent/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/superagent/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/superagent/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/superagent/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/supertest": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.4.2.tgz", - "integrity": "sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "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==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dependencies": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/toposort-class": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "engines": { - "node": ">=4" - } - }, - "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, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" - }, - "node_modules/uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dependencies": { - "random-bytes": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/umzug": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", - "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", - "dependencies": { - "bluebird": "^3.7.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validator": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", - "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/version-guard": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/version-guard/-/version-guard-1.1.1.tgz", - "integrity": "sha512-MGQLX89UxmYHgDvcXyjBI0cbmoW+t/dANDppNPrno64rYr8nH4SHSuElQuSYdXGEs0mUzdQe1BY+FhVPNsAmJQ==", - "dev": true, - "engines": { - "node": ">=0.10.48" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", - "dev": true, - "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" - }, - "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wkx": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" - }, - "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/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "extraneous": true - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "extraneous": true - }, - "passport": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", - "extraneous": true - }, - "passport-jwt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", - "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", - "extraneous": true - }, - "passport-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", - "extraneous": true - }, - "passport-strategy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", - "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", - "extraneous": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "extraneous": true, - "engines": { - "node": ">=4" - } - } - } -} From a44fee491d5377bdcca9fd69e2fa353897c268a4 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Mon, 4 Sep 2023 20:24:14 +0800 Subject: [PATCH 162/170] fix :jwt sectet --- config/passport.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/passport.js b/config/passport.js index 256593eb74..b5c53a06c0 100644 --- a/config/passport.js +++ b/config/passport.js @@ -7,7 +7,7 @@ const ExtractJWT = passportJWT.ExtractJwt const jwtOptions = { jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken(), - secretOrKey: process.env.JWT_SECRET + secretOrKey: process.env.JWT_SECRET || 'Secret' } passport.use( new JWTStrategy(jwtOptions, (jwtPayload, cb) => { From 7c8f781ec36ddde66035dafff7ba2a9a6694fdce Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Mon, 4 Sep 2023 21:21:47 +0800 Subject: [PATCH 163/170] fix: conflict --- routes/modules/admin.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 74129a245e..9d8f10aaa4 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -1,19 +1,9 @@ const express = require('express') const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') -<<<<<<< HEAD -const passport = require('passport') + const { authenticated, authenticatedAdmin } = require('../middleware/api-auth') // router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) -======= - -const { - authenticated, - authenticatedAdmin -} = require('../../middleware/api-auth') - -router.post('/signin', adminController.signIn) ->>>>>>> 4397115c6ac10aa993d100d5a86d715bf599b3af router.get( '/users', From a3f10e1fbf09d2f1b1e800ef38e111aadf6570bc Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Mon, 4 Sep 2023 21:27:22 +0800 Subject: [PATCH 164/170] fix: error --- routes/modules/admin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 9d8f10aaa4..a8453a2677 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -2,7 +2,7 @@ const express = require('express') const router = express.Router() const adminController = require('../../controllers/apis/admin-controller') -const { authenticated, authenticatedAdmin } = require('../middleware/api-auth') +const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') // router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) router.get( From cb088e2fa66101015afabed8b83875deb1a3e959 Mon Sep 17 00:00:00 2001 From: yiching-hsu Date: Mon, 4 Sep 2023 21:36:54 +0800 Subject: [PATCH 165/170] fix: package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 17d91bfbaa..7c8ccb5f96 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "start": "NODE_ENV=development node app.js", "dev": "NODE_ENV=development nodemon app.js", "lint": "eslint \"**/*.js\" --fix", - "test": "NODE_ENV=test mocha test --exit --recursive --timeout 5000" + "test": "mocha test --exit --recursive --timeout 5000" }, "engines": { "node": "18.15.0" From 0d1ed2feb9e8a86d34a17c9754cbfe6bc4b92c55 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 3 Nov 2023 16:10:18 +0800 Subject: [PATCH 166/170] fix: production database --- config/config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/config/config.json b/config/config.json index 5e4a51b957..3646ce8f90 100644 --- a/config/config.json +++ b/config/config.json @@ -15,6 +15,7 @@ "logging": false }, "production": { + "database" : "ac_twitter_workspace", "use_env_variable": "MYSQL_DATABASE_URL" }, "travis": { From 381a4d0061e0930ecac0f07d9b1ac59f95ab2c80 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 3 Nov 2023 16:18:50 +0800 Subject: [PATCH 167/170] fix env --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 1b9cb8453e..f709f12b29 100644 --- a/app.js +++ b/app.js @@ -1,4 +1,4 @@ -if (process.NODE_ENV !== 'production') { +if (process.env.NODE_ENV !== 'production') { require('dotenv').config() } const cors = require('cors') From 010373f50497c861b7579d9ec353ac0be3da698f Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 3 Nov 2023 16:24:20 +0800 Subject: [PATCH 168/170] config add dialect --- config/config.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/config/config.json b/config/config.json index 3646ce8f90..ceb27d1a37 100644 --- a/config/config.json +++ b/config/config.json @@ -15,6 +15,10 @@ "logging": false }, "production": { + "username": "root", + "password": null, + "host": "127.0.0.1", + "dialect": "mysql", "database" : "ac_twitter_workspace", "use_env_variable": "MYSQL_DATABASE_URL" }, From 2e428209bdddb78d2140d6381f530c642c720ae8 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Fri, 3 Nov 2023 16:33:33 +0800 Subject: [PATCH 169/170] database = railway --- config/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.json b/config/config.json index ceb27d1a37..9a5d23d34d 100644 --- a/config/config.json +++ b/config/config.json @@ -19,7 +19,7 @@ "password": null, "host": "127.0.0.1", "dialect": "mysql", - "database" : "ac_twitter_workspace", + "database" : "railway", "use_env_variable": "MYSQL_DATABASE_URL" }, "travis": { From c7d2fd0cdf4f31c8ce57cfd81dc82a65502d1c27 Mon Sep 17 00:00:00 2001 From: Sean Chen Date: Wed, 15 Nov 2023 20:30:12 +0800 Subject: [PATCH 170/170] fix: admin signin --- routes/modules/admin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/modules/admin.js b/routes/modules/admin.js index a8453a2677..05e468387f 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -4,7 +4,7 @@ const adminController = require('../../controllers/apis/admin-controller') const { authenticated, authenticatedAdmin } = require('../../middleware/api-auth') // router.post('/login', passport.authenticate('jwt', { session: false }), adminController.signIn) - +router.post('/signin', adminController.signIn) router.get( '/users', authenticated,