From 4329f793bce7466eb427d4965b78a432781b3978 Mon Sep 17 00:00:00 2001 From: alvin Date: Sun, 4 Jun 2023 09:00:51 +0800 Subject: [PATCH 001/232] =?UTF-8?q?feat:=20=E5=88=9D=E5=A7=8B=E5=8C=96?= =?UTF-8?q?=E5=B0=88=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 2 +- config/config.json | 2 +- models/reply.js | 12 +- package-lock.json | 3216 +------------------------------------------- package.json | 6 +- 5 files changed, 30 insertions(+), 3208 deletions(-) diff --git a/app.js b/app.js index 80ee0bbf8..450a84817 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,5 @@ const express = require('express') -const helpers = require('./_helpers'); +const helpers = require('./_helpers') const app = express() const port = 3000 diff --git a/config/config.json b/config/config.json index 64b9997e4..6b1611dc3 100644 --- a/config/config.json +++ b/config/config.json @@ -28,4 +28,4 @@ "dialect": "mysql", "logging": false } -} \ No newline at end of file +} diff --git a/models/reply.js b/models/reply.js index 60387f164..b826a1018 100644 --- a/models/reply.js +++ b/models/reply.js @@ -1,8 +1,6 @@ -'use strict'; +'use strict' module.exports = (sequelize, DataTypes) => { - const Reply = sequelize.define('Reply', { - }, {}); - Reply.associate = function(models) { - }; - return Reply; -}; \ No newline at end of file + const Reply = sequelize.define('Reply', {}, {}) + Reply.associate = function (models) {} + return Reply +} diff --git a/package-lock.json b/package-lock.json index 0307072c0..1b0bc0cca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,3182 +1,8 @@ { "name": "test", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "test", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "bcrypt-nodejs": "0.0.3", - "body-parser": "^1.18.3", - "chai": "^4.2.0", - "connect-flash": "^0.1.1", - "express": "^4.16.4", - "express-handlebars": "^3.0.0", - "express-session": "^1.15.6", - "faker": "^4.1.0", - "method-override": "^3.0.0", - "mocha": "^6.0.2", - "mysql2": "^1.6.4", - "passport": "^0.4.0", - "passport-local": "^1.0.0", - "sequelize": "^6.18.0", - "sequelize-cli": "^5.5.0", - "sinon": "^10.0.0", - "sinon-chai": "^3.3.0" - }, - "devDependencies": { - "proxyquire": "^2.1.3", - "sequelize-test-helpers": "^1.4.2", - "supertest": "^3.3.0" - } - }, - "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==", - "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.1", - "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/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", - "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/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": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "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/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/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "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/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "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-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/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.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==", - "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.10.3", - "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/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/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/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/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.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dependencies": { - "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" - }, - "engines": { - "node": ">=4" - } - }, - "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/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" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "engines": { - "node": "*" - } - }, - "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==", - "dependencies": { - "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" - } - }, - "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/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/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/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "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==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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==" - }, - "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": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "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": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=", - "engines": { - "node": ">= 0.4.0" - } - }, - "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.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "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/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", - "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==", - "dev": true - }, - "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": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "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==", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "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==", - "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": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", - "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/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/dottie": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", - "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" - }, - "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==", - "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "bin": { - "editorconfig": "bin/editorconfig" - } - }, - "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==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "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/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "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/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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.60", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", - "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", - "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": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "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/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "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=", - "engines": { - "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==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "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": { - "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==", - "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" - } - }, - "node_modules/express-handlebars": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-3.1.0.tgz", - "integrity": "sha512-7QlaXnSREMmN5P2o4gmpUZDfJlLtfBka9d6r7/ccXaU7rPp76odw9YYtwZYdIiha2JqwiaG6o2Wu6NZJQ0u7Fg==", - "dependencies": { - "glob": "^7.1.3", - "graceful-fs": "^4.1.2", - "handlebars": "^4.1.2", - "object.assign": "^4.1.0", - "promise": "^8.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "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": ">= 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", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "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" - }, - "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" - }, - "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_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": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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": { - "type": "^2.5.0" - } - }, - "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==", - "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/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": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "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" - }, - "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==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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/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": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "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==", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "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==", - "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": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "engines": { - "node": "*" - } - }, - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "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/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==", - "engines": { - "node": ">=4.x" - } - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "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.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/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-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/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": { - "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/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/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/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=", - "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.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dependencies": { - "get-intrinsic": "^1.1.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-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.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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-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/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-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": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "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-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/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "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/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": { - "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" - } - }, - "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/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/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==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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/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/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==", - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "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==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "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/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.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": "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": { - "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": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "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/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.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "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/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/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/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/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/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": "*" - } - }, - "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": { - "moment": ">= 2.9.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==", - "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" - }, - "engines": { - "node": ">= 8.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==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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": { - "lru-cache": "^4.1.3" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "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": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "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/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/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "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": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "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-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==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "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==", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "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==", - "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/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": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "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/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/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/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-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", - "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": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", - "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=", - "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=", - "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_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/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/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/promise": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", - "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", - "dependencies": { - "asap": "~2.0.6" - } - }, - "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/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/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "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/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/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/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.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dependencies": { - "is-core-module": "^2.8.1", - "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/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/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/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.19.0", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.19.0.tgz", - "integrity": "sha512-B3oGIdpYBERDjRDm74h7Ky67f6ZLcmBXOA7HscYObiOSo4pD7VBc9mtm44wNV7unc0uk8I1d30nbZBTQCE377A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/sequelize" - } - ], - "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" - }, - "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 - } - } - }, - "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==", - "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" - }, - "bin": { - "sequelize": "lib/sequelize", - "sequelize-cli": "lib/sequelize" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "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.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/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/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/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/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/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/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "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/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.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/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==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "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-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/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/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-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-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/uglify-js": { - "version": "3.15.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.4.tgz", - "integrity": "sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.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==", - "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.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" - }, - "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/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/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-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "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/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, - "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/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/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" - } - } - }, "dependencies": { "@sinonjs/commons": { "version": "1.8.3", @@ -5121,8 +1947,7 @@ "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": {} + "dev": true }, "serve-static": { "version": "1.14.2", @@ -5196,8 +2021,7 @@ "sinon-chai": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "requires": {} + "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==" }, "source-map": { "version": "0.6.1", @@ -5219,23 +2043,6 @@ "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==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -5263,6 +2070,23 @@ "define-properties": "^1.1.3" } }, + "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, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", diff --git a/package.json b/package.json index e85b8c07c..e2ae473bb 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "start": "NODE_ENV=development node app.js", - "dev": "NODE_ENV=development nodemon app.js", - "test": "mocha test --exit --recursive --timeout 5000" + "start": "set \"NODE_ENV=development\" && node app.js", + "dev": "set \"NODE_ENV=development\" && nodemon app.js", + "test": "set \"NODE_ENV=test\" && mocha test --exit --recursive --timeout 5000" }, "author": "", "license": "ISC", From 1edc426abeb66156e7f0ac3c0593f2624f1ea6fe Mon Sep 17 00:00:00 2001 From: Suz033 Date: Sun, 4 Jun 2023 15:04:30 +0800 Subject: [PATCH 002/232] feat: add public/images files --- public/images/add_photo.svg | 4 ++++ public/images/back.svg | 3 +++ public/images/chat_filled.svg | 3 +++ public/images/chat_outlined.svg | 4 ++++ public/images/close.svg | 3 +++ public/images/like_filled.svg | 3 +++ public/images/like_outlined.svg | 3 +++ public/images/logo.svg | 6 ++++++ public/images/message/message_danger.svg | 10 ++++++++++ public/images/message/message_info.svg | 10 ++++++++++ public/images/message/message_success.svg | 10 ++++++++++ public/images/message/message_warning.svg | 10 ++++++++++ public/images/navbar/cog_filled.svg | 3 +++ public/images/navbar/cog_outlined.svg | 4 ++++ public/images/navbar/home_filled.svg | 3 +++ public/images/navbar/home_outlined.svg | 4 ++++ public/images/navbar/logout.svg | 4 ++++ public/images/navbar/user_filled.svg | 3 +++ public/images/navbar/user_outlined.svg | 3 +++ public/images/post.svg | 3 +++ public/images/profile-img.svg | 7 +++++++ public/images/profile/mail_filled.svg | 4 ++++ public/images/profile/mail_outlined.svg | 3 +++ public/images/profile/notification_filled.svg | 10 ++++++++++ public/images/profile/notification_outlined.svg | 3 +++ public/images/reply_outlined.svg | 3 +++ 26 files changed, 126 insertions(+) create mode 100644 public/images/add_photo.svg create mode 100644 public/images/back.svg create mode 100644 public/images/chat_filled.svg create mode 100644 public/images/chat_outlined.svg create mode 100644 public/images/close.svg create mode 100644 public/images/like_filled.svg create mode 100644 public/images/like_outlined.svg create mode 100644 public/images/logo.svg create mode 100644 public/images/message/message_danger.svg create mode 100644 public/images/message/message_info.svg create mode 100644 public/images/message/message_success.svg create mode 100644 public/images/message/message_warning.svg create mode 100644 public/images/navbar/cog_filled.svg create mode 100644 public/images/navbar/cog_outlined.svg create mode 100644 public/images/navbar/home_filled.svg create mode 100644 public/images/navbar/home_outlined.svg create mode 100644 public/images/navbar/logout.svg create mode 100644 public/images/navbar/user_filled.svg create mode 100644 public/images/navbar/user_outlined.svg create mode 100644 public/images/post.svg create mode 100644 public/images/profile-img.svg create mode 100644 public/images/profile/mail_filled.svg create mode 100644 public/images/profile/mail_outlined.svg create mode 100644 public/images/profile/notification_filled.svg create mode 100644 public/images/profile/notification_outlined.svg create mode 100644 public/images/reply_outlined.svg diff --git a/public/images/add_photo.svg b/public/images/add_photo.svg new file mode 100644 index 000000000..aa45dc63f --- /dev/null +++ b/public/images/add_photo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/back.svg b/public/images/back.svg new file mode 100644 index 000000000..423d33a45 --- /dev/null +++ b/public/images/back.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/chat_filled.svg b/public/images/chat_filled.svg new file mode 100644 index 000000000..0f7e9fdd4 --- /dev/null +++ b/public/images/chat_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/chat_outlined.svg b/public/images/chat_outlined.svg new file mode 100644 index 000000000..622cef588 --- /dev/null +++ b/public/images/chat_outlined.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/close.svg b/public/images/close.svg new file mode 100644 index 000000000..013406203 --- /dev/null +++ b/public/images/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/like_filled.svg b/public/images/like_filled.svg new file mode 100644 index 000000000..ed5dd2c61 --- /dev/null +++ b/public/images/like_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/like_outlined.svg b/public/images/like_outlined.svg new file mode 100644 index 000000000..cc2528848 --- /dev/null +++ b/public/images/like_outlined.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/logo.svg b/public/images/logo.svg new file mode 100644 index 000000000..e323e4578 --- /dev/null +++ b/public/images/logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/images/message/message_danger.svg b/public/images/message/message_danger.svg new file mode 100644 index 000000000..afe31c550 --- /dev/null +++ b/public/images/message/message_danger.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/images/message/message_info.svg b/public/images/message/message_info.svg new file mode 100644 index 000000000..20b52cc2b --- /dev/null +++ b/public/images/message/message_info.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/images/message/message_success.svg b/public/images/message/message_success.svg new file mode 100644 index 000000000..4615a6ff4 --- /dev/null +++ b/public/images/message/message_success.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/images/message/message_warning.svg b/public/images/message/message_warning.svg new file mode 100644 index 000000000..bb17d9871 --- /dev/null +++ b/public/images/message/message_warning.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/images/navbar/cog_filled.svg b/public/images/navbar/cog_filled.svg new file mode 100644 index 000000000..005e625e1 --- /dev/null +++ b/public/images/navbar/cog_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/navbar/cog_outlined.svg b/public/images/navbar/cog_outlined.svg new file mode 100644 index 000000000..6db284e9b --- /dev/null +++ b/public/images/navbar/cog_outlined.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/navbar/home_filled.svg b/public/images/navbar/home_filled.svg new file mode 100644 index 000000000..318a60a36 --- /dev/null +++ b/public/images/navbar/home_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/navbar/home_outlined.svg b/public/images/navbar/home_outlined.svg new file mode 100644 index 000000000..0d8b9c8e8 --- /dev/null +++ b/public/images/navbar/home_outlined.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/navbar/logout.svg b/public/images/navbar/logout.svg new file mode 100644 index 000000000..5a642c512 --- /dev/null +++ b/public/images/navbar/logout.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/navbar/user_filled.svg b/public/images/navbar/user_filled.svg new file mode 100644 index 000000000..013d77eba --- /dev/null +++ b/public/images/navbar/user_filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/navbar/user_outlined.svg b/public/images/navbar/user_outlined.svg new file mode 100644 index 000000000..3e267bd8e --- /dev/null +++ b/public/images/navbar/user_outlined.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/post.svg b/public/images/post.svg new file mode 100644 index 000000000..3bd766f0a --- /dev/null +++ b/public/images/post.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/profile-img.svg b/public/images/profile-img.svg new file mode 100644 index 000000000..3065dae79 --- /dev/null +++ b/public/images/profile-img.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/public/images/profile/mail_filled.svg b/public/images/profile/mail_filled.svg new file mode 100644 index 000000000..5a4610f5c --- /dev/null +++ b/public/images/profile/mail_filled.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/images/profile/mail_outlined.svg b/public/images/profile/mail_outlined.svg new file mode 100644 index 000000000..12339b63e --- /dev/null +++ b/public/images/profile/mail_outlined.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/profile/notification_filled.svg b/public/images/profile/notification_filled.svg new file mode 100644 index 000000000..1ffea968d --- /dev/null +++ b/public/images/profile/notification_filled.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/images/profile/notification_outlined.svg b/public/images/profile/notification_outlined.svg new file mode 100644 index 000000000..7ab166713 --- /dev/null +++ b/public/images/profile/notification_outlined.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/images/reply_outlined.svg b/public/images/reply_outlined.svg new file mode 100644 index 000000000..eef025775 --- /dev/null +++ b/public/images/reply_outlined.svg @@ -0,0 +1,3 @@ + + + From 7fdf5b2ae583190affa2b203ab82ead64ed04000 Mon Sep 17 00:00:00 2001 From: Suz033 Date: Sun, 4 Jun 2023 15:06:27 +0800 Subject: [PATCH 003/232] feat: add home page --- app.js | 16 +- package-lock.json | 3221 +---------------------- public/stylesheets/style.css | 219 ++ views/layouts/main.hbs | 52 + views/partials/navbar.hbs | 39 + views/partials/recommend-followings.hbs | 198 ++ 6 files changed, 546 insertions(+), 3199 deletions(-) create mode 100644 public/stylesheets/style.css create mode 100644 views/layouts/main.hbs create mode 100644 views/partials/navbar.hbs create mode 100644 views/partials/recommend-followings.hbs diff --git a/app.js b/app.js index 80ee0bbf8..eafec81f5 100644 --- a/app.js +++ b/app.js @@ -1,13 +1,23 @@ +// modules const express = require('express') -const helpers = require('./_helpers'); - const app = express() +const handlebars = require('express-handlebars') + +// files +const helpers = require('./_helpers') +app.use(express.static('public')) + const port = 3000 +app.engine('hbs', handlebars({ extname: '.hbs', defaultLayout: 'main' })) +app.set('view engine', 'hbs') + // use helpers.getUser(req) to replace req.user // use helpers.ensureAuthenticated(req) to replace req.isAuthenticated() -app.get('/', (req, res) => res.send('Hello World!')) +// routes +app.get('/', (req, res) => res.render('index')) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) +// exports module.exports = app diff --git a/package-lock.json b/package-lock.json index 0307072c0..8fbfb6417 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,3182 +1,8 @@ { "name": "test", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "test", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "bcrypt-nodejs": "0.0.3", - "body-parser": "^1.18.3", - "chai": "^4.2.0", - "connect-flash": "^0.1.1", - "express": "^4.16.4", - "express-handlebars": "^3.0.0", - "express-session": "^1.15.6", - "faker": "^4.1.0", - "method-override": "^3.0.0", - "mocha": "^6.0.2", - "mysql2": "^1.6.4", - "passport": "^0.4.0", - "passport-local": "^1.0.0", - "sequelize": "^6.18.0", - "sequelize-cli": "^5.5.0", - "sinon": "^10.0.0", - "sinon-chai": "^3.3.0" - }, - "devDependencies": { - "proxyquire": "^2.1.3", - "sequelize-test-helpers": "^1.4.2", - "supertest": "^3.3.0" - } - }, - "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==", - "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.1", - "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/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", - "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/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": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "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/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/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "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/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "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-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/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.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==", - "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.10.3", - "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/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/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/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/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.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", - "dependencies": { - "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" - }, - "engines": { - "node": ">=4" - } - }, - "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/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" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "engines": { - "node": "*" - } - }, - "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==", - "dependencies": { - "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" - } - }, - "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/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/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/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "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==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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==" - }, - "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": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "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": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=", - "engines": { - "node": ">= 0.4.0" - } - }, - "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.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "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/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==", - "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==", - "dev": true - }, - "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": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "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==", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "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==", - "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": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", - "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/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/dottie": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", - "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" - }, - "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==", - "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "bin": { - "editorconfig": "bin/editorconfig" - } - }, - "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==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "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/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "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/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "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==", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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.60", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", - "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", - "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": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "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/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "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=", - "engines": { - "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==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "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": { - "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==", - "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" - } - }, - "node_modules/express-handlebars": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-3.1.0.tgz", - "integrity": "sha512-7QlaXnSREMmN5P2o4gmpUZDfJlLtfBka9d6r7/ccXaU7rPp76odw9YYtwZYdIiha2JqwiaG6o2Wu6NZJQ0u7Fg==", - "dependencies": { - "glob": "^7.1.3", - "graceful-fs": "^4.1.2", - "handlebars": "^4.1.2", - "object.assign": "^4.1.0", - "promise": "^8.0.2" - }, - "engines": { - "node": ">=0.10" - } - }, - "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": ">= 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", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", - "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" - }, - "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" - }, - "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_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": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "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": { - "type": "^2.5.0" - } - }, - "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==", - "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/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": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "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" - }, - "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==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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/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": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "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==", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "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==", - "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": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "engines": { - "node": "*" - } - }, - "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" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "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/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==", - "engines": { - "node": ">=4.x" - } - }, - "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "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.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/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-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/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": { - "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/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/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/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=", - "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.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dependencies": { - "get-intrinsic": "^1.1.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-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.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "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-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/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-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": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "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-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/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "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/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": { - "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" - } - }, - "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/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/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==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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/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/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==", - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "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==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "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/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.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": "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": { - "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": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "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/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.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "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/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/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/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/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/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": "*" - } - }, - "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": { - "moment": ">= 2.9.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==", - "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" - }, - "engines": { - "node": ">= 8.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==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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": { - "lru-cache": "^4.1.3" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "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": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "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/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/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "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": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "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-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==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "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==", - "engines": { - "node": ">= 0.4" - } - }, - "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==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "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==", - "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/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": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "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/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/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/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-local": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", - "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", - "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": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=", - "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=", - "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=", - "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_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/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/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/promise": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", - "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", - "dependencies": { - "asap": "~2.0.6" - } - }, - "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/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/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "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/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/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/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.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dependencies": { - "is-core-module": "^2.8.1", - "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/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/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/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.19.0", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.19.0.tgz", - "integrity": "sha512-B3oGIdpYBERDjRDm74h7Ky67f6ZLcmBXOA7HscYObiOSo4pD7VBc9mtm44wNV7unc0uk8I1d30nbZBTQCE377A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/sequelize" - } - ], - "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" - }, - "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 - } - } - }, - "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==", - "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" - }, - "bin": { - "sequelize": "lib/sequelize", - "sequelize-cli": "lib/sequelize" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "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.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/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/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/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/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/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/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "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/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.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/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==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "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-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/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/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-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-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/uglify-js": { - "version": "3.15.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.4.tgz", - "integrity": "sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.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==", - "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.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" - }, - "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/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/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-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" - }, - "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/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, - "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/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/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" - } - } - }, "dependencies": { "@sinonjs/commons": { "version": "1.8.3", @@ -3327,6 +153,11 @@ "unpipe": "1.0.0" } }, + "bootstrap": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", + "integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5121,8 +1952,7 @@ "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": {} + "dev": true }, "serve-static": { "version": "1.14.2", @@ -5196,8 +2026,7 @@ "sinon-chai": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", - "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "requires": {} + "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==" }, "source-map": { "version": "0.6.1", @@ -5219,23 +2048,6 @@ "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==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -5263,6 +2075,23 @@ "define-properties": "^1.1.3" } }, + "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, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css new file mode 100644 index 000000000..a7ad0a210 --- /dev/null +++ b/public/stylesheets/style.css @@ -0,0 +1,219 @@ +/****** body ******/ +html, +body { + height: 100vh; + margin: 0; + overflow-y: hidden; +} + + + +/****** home ******/ +.home-page { + margin: 0px 24px; + padding: 0; + border: 1px solid #E6ECF0; + overflow-y: hidden; +} + +.tweet-list { + border: 0px; + border-radius: 0 !important; + border-bottom: 1px solid #E6ECF0; +} + + + +/****** nav ******/ +.navbar.navbar-vertical { + padding: 0; +} + +.navbar-nav { + height: 100vh; + padding-top: 13px; + padding-bottom: 16px; +} + +.navbar-nav .nav-item .nav-link { + display: flex; + align-items: center; + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 700; + font-size: 18px; + line-height: 26px; + color: #44444F; +} + +.navbar-nav .nav-item.active .nav-link { + color: #FF6600; +} + +.navbar-nav .nav-item .nav-link .nav-text { + margin-left: 16.9px; +} + +.navbar-nav .nav-item .nav-link .nav-icon { + width: 24px; + height: 24px; + background-repeat: no-repeat; + background-position: center; + background-size: cover; +} + + +/* nav-icon */ +.navbar-nav .nav-item.active .nav-link .home-icon { + background-image: url('/images/navbar/home_filled.svg'); +} +.navbar-nav .nav-item .nav-link .home-icon { + background-image: url('/images/navbar/home_outlined.svg'); +} + +.navbar-nav .nav-item.active .nav-link .user-icon { + background-image: url('/images/navbar/user_filled.svg'); +} +.navbar-nav .nav-item .nav-link .user-icon { + background-image: url('/images/navbar/user_outlined.svg'); +} + +.navbar-nav .nav-item.active .nav-link .cog-icon { + background-image: url('/images/navbar/cog_filled.svg'); +} +.navbar-nav .nav-item .nav-link .cog-icon { + background-image: url('/images/navbar/cog_outlined.svg'); +} + +.navbar-nav .nav-item .nav-link .logout-icon { + background-image: url('/images/navbar/logout.svg'); +} + + +/****** btn ******/ +.btn { + /* Auto layout */ + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 8px auto; + + /* color/brand/main */ + + background: #FF6600; + border-radius: 50px; + border-color: #FF6600; + + /* Inside auto layout */ + + flex: none; + order: 0; + align-self: stretch; + flex-grow: 0; + + + + /* Global/09. White */ + + color: #FFFFFF; +} + +.btn:hover { + color: #FFFFFF; + background: #FF6600; + border-color: #FF6600; + transform: scale(1.05); +} + +.btn:active { + color: #FF6600 !important; + background-color: #FFFFFF !important; + border-color: #FF6600 !important; +} + +.nav-btn { + /* btn */ + max-width: 178px; + height: 46px; + + /* font */ + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 400; + font-size: 20px; +} + +.recommend-followings-btn { + /* btn */ + width: auto; + height: 40px; + background: #FFFFFF; + border: 1px solid #FF6600; + + /* font */ + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 400; + font-size: 16px; + color: #FF6600; +} + +.recommend-followings-btn.followed { + background: #FF6600; + border: 1px solid #FF6600; + color: #FFFFFF; +} + + +/****** recommend-followings ******/ +.recommend-followings { + /* Right Column */ + height: calc(100vh - 2rem); + max-width: 273px; + overflow-y: auto; + + border-radius: 16px; +} + +.recommend-followings-item { + background: #FAFAFB; + border: 0; + padding: 0.8vw; +} + +.recommend-followings-title { + background: #FAFAFB; + border-bottom: 1px solid #E6ECF0; +} + +.recommend-followings-img { + max-width: 100%; + height: auto; +} + +.recommend-followings-text { + margin-left: 8px; + margin-right: 3px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 76px; +} + +.follower-name { + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 700; + font-size: 16px; + color: #171725; +} + +.follower-account { + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 500; + font-size: 14px; + color: #92929D; +} \ No newline at end of file diff --git a/views/layouts/main.hbs b/views/layouts/main.hbs new file mode 100644 index 000000000..ddaf324c1 --- /dev/null +++ b/views/layouts/main.hbs @@ -0,0 +1,52 @@ + + + + + + + + Twitter + + {{!-- logo --}} + + + {{!-- bootstrap --}} + + + {{!-- css --}} + + + + + +
+
+ {{!-- navbar --}} + {{> navbar}} + + {{!--tweet-list --}} +
+
    +
  • +

    首頁

    +
  • +
+
+ + {{!-- recommend-followings --}} + {{> recommend-followings}} + +
+ +
+ + + + {{{ body }}} + + + {{!-- bootstrap --}} + + + + \ No newline at end of file diff --git a/views/partials/navbar.hbs b/views/partials/navbar.hbs new file mode 100644 index 000000000..334a3755f --- /dev/null +++ b/views/partials/navbar.hbs @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/views/partials/recommend-followings.hbs b/views/partials/recommend-followings.hbs new file mode 100644 index 000000000..148ef95e8 --- /dev/null +++ b/views/partials/recommend-followings.hbs @@ -0,0 +1,198 @@ +
+
    +
  • +

    推薦跟隨

    +
  • + +
  • +
    +
    + +
    +
    +
    Pizza Hut
    + +
    + +
    +
  • + +
  • +
    +
    + +
    +
    +
    McDon ...
    + +
    + +
    +
  • + +
  • +
    +
    + +
    +
    +
    Bank of ...
    + +
    +
    + 跟隨 +
    +
    +
  • + +
  • +
    +
    + +
    +
    +
    L'Oréal
    + +
    +
    + 跟隨 +
    +
    +
  • + +
  • +
    +
    + +
    +
    +
    Nintendo
    + +
    +
    + 跟隨 +
    +
    +
  • + +
  • +
    +
    + +
    +
    +
    MasterCard
    + +
    +
    + 跟隨 +
    +
    +
  • + +
  • +
    +
    + +
    +
    +
    Nike
    + +
    +
    + 跟隨 +
    +
    +
  • + +
  • +
    +
    + +
    +
    +
    Adidas
    + +
    +
    + 跟隨 +
    +
    +
  • + +
  • +
    +
    + +
    +
    +
    McDon ...
    + +
    +
    + 跟隨 +
    +
    +
  • +
  • +
    +
    + +
    +
    +
    McDon ...
    + +
    +
    + 跟隨 +
    +
    +
  • +
  • +
    +
    + +
    +
    +
    McDon ...
    + +
    +
    + 跟隨 +
    +
    +
  • +
  • +
    +
    + +
    +
    +
    McDon ...
    + +
    +
    + 跟隨 +
    +
    +
  • +
  • +
    +
    + +
    +
    +
    McDon ...
    + +
    +
    + 跟隨 +
    +
    +
  • +
+
\ No newline at end of file From b39360e42356f7c428ad1d43ca4d5be2f25e011e Mon Sep 17 00:00:00 2001 From: alvin Date: Sun, 4 Jun 2023 15:43:02 +0800 Subject: [PATCH 004/232] =?UTF-8?q?feat:=20=E5=BB=BA=E7=AB=8Bmodel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 3 ++ .../20190115071418-create-followship.js | 16 +++--- migrations/20190115071419-create-like.js | 16 +++--- migrations/20190115071420-create-reply.js | 19 ++++--- migrations/20190115071420-create-tweet.js | 17 +++--- migrations/20190115071421-create-user.js | 21 +++++--- models/followship.js | 31 ++++++++--- models/like.js | 35 ++++++++++--- models/reply.js | 28 +++++++++- models/tweet.js | 36 ++++++++++--- models/user.js | 52 ++++++++++++++++--- 11 files changed, 207 insertions(+), 67 deletions(-) diff --git a/app.js b/app.js index 450a84817..107d67266 100644 --- a/app.js +++ b/app.js @@ -1,5 +1,8 @@ const express = require('express') +const exphbs = require('express-handlebars') + const helpers = require('./_helpers') +const handlebarsHelpers = require('./helpers/handlebars-helpers') const app = express() const port = 3000 diff --git a/migrations/20190115071418-create-followship.js b/migrations/20190115071418-create-followship.js index 4e04770a7..da1802d87 100644 --- a/migrations/20190115071418-create-followship.js +++ b/migrations/20190115071418-create-followship.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('Followships', { @@ -8,23 +8,23 @@ module.exports = { primaryKey: true, type: Sequelize.INTEGER }, - followerId: { + follower_id: { type: Sequelize.INTEGER }, - followingId: { + following_id: { type: Sequelize.INTEGER }, - createdAt: { + created_at: { allowNull: false, type: Sequelize.DATE }, - updatedAt: { + updated_at: { allowNull: false, type: Sequelize.DATE } - }); + }) }, down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Followships'); + return queryInterface.dropTable('Followships') } -}; \ No newline at end of file +} diff --git a/migrations/20190115071419-create-like.js b/migrations/20190115071419-create-like.js index 08c9e524d..5d7dfe240 100644 --- a/migrations/20190115071419-create-like.js +++ b/migrations/20190115071419-create-like.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('Likes', { @@ -8,23 +8,23 @@ module.exports = { primaryKey: true, type: Sequelize.INTEGER }, - UserId: { + User_id: { type: Sequelize.INTEGER }, - TweetId: { + Tweet_id: { type: Sequelize.INTEGER }, - createdAt: { + created_at: { allowNull: false, type: Sequelize.DATE }, - updatedAt: { + updated_at: { allowNull: false, type: Sequelize.DATE } - }); + }) }, down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Likes'); + return queryInterface.dropTable('Likes') } -}; \ No newline at end of file +} diff --git a/migrations/20190115071420-create-reply.js b/migrations/20190115071420-create-reply.js index ccfd119c5..445287248 100644 --- a/migrations/20190115071420-create-reply.js +++ b/migrations/20190115071420-create-reply.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('Replies', { @@ -8,26 +8,29 @@ module.exports = { primaryKey: true, type: Sequelize.INTEGER }, - UserId: { + User_id: { type: Sequelize.INTEGER }, - TweetId: { + Tweet_id: { type: Sequelize.INTEGER }, comment: { type: Sequelize.TEXT }, - createdAt: { + deleted_at: { + type: Sequelize.DATE + }, + created_at: { allowNull: false, type: Sequelize.DATE }, - updatedAt: { + updated_at: { allowNull: false, type: Sequelize.DATE } - }); + }) }, down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Replies'); + return queryInterface.dropTable('Replies') } -}; \ No newline at end of file +} diff --git a/migrations/20190115071420-create-tweet.js b/migrations/20190115071420-create-tweet.js index 201c8e824..daf72e5c8 100644 --- a/migrations/20190115071420-create-tweet.js +++ b/migrations/20190115071420-create-tweet.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('Tweets', { @@ -8,23 +8,26 @@ module.exports = { primaryKey: true, type: Sequelize.INTEGER }, - UserId: { + User_id: { type: Sequelize.INTEGER }, description: { type: Sequelize.TEXT }, - createdAt: { + deleted_at: { + type: Sequelize.DATE + }, + created_at: { allowNull: false, type: Sequelize.DATE }, - updatedAt: { + updated_at: { allowNull: false, type: Sequelize.DATE } - }); + }) }, down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Tweets'); + return queryInterface.dropTable('Tweets') } -}; \ No newline at end of file +} diff --git a/migrations/20190115071421-create-user.js b/migrations/20190115071421-create-user.js index 2376dbb50..21cb835ed 100644 --- a/migrations/20190115071421-create-user.js +++ b/migrations/20190115071421-create-user.js @@ -1,4 +1,4 @@ -'use strict'; +'use strict' module.exports = { up: (queryInterface, Sequelize) => { return queryInterface.createTable('Users', { @@ -14,29 +14,38 @@ module.exports = { password: { type: Sequelize.STRING }, + account: { + type: Sequelize.STRING + }, name: { type: Sequelize.STRING }, avatar: { type: Sequelize.STRING }, + cover: { + type: Sequelize.STRING + }, introduction: { type: Sequelize.TEXT }, role: { type: Sequelize.STRING }, - createdAt: { + deleted_at: { + type: Sequelize.DATE + }, + created_at: { allowNull: false, type: Sequelize.DATE }, - updatedAt: { + updated_at: { allowNull: false, type: Sequelize.DATE } - }); + }) }, down: (queryInterface, Sequelize) => { - return queryInterface.dropTable('Users'); + return queryInterface.dropTable('Users') } -}; \ No newline at end of file +} diff --git a/models/followship.js b/models/followship.js index 790f3faa3..af5fa7d65 100644 --- a/models/followship.js +++ b/models/followship.js @@ -1,8 +1,25 @@ -'use strict'; +'use strict' +const { Model } = require('sequelize') module.exports = (sequelize, DataTypes) => { - const Followship = sequelize.define('Followship', { - }, {}); - Followship.associate = function(models) { - }; - return Followship; -}; \ No newline at end of file + 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) {} + } + Followship.init( + { + followerId: DataTypes.INTEGER, + followingId: DataTypes.INTEGER + }, + { + sequelize, + modelName: 'Followship', + tableName: 'Followships', + underscored: true + } + ) + return Followship +} diff --git a/models/like.js b/models/like.js index c8939de1f..65048f504 100644 --- a/models/like.js +++ b/models/like.js @@ -1,8 +1,29 @@ -'use strict'; +'use strict' + +const { Model } = require('sequelize') module.exports = (sequelize, DataTypes) => { - const Like = sequelize.define('Like', { - }, {}); - Like.associate = function(models) { - }; - return Like; -}; \ No newline at end of file + 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) { + Like.belongsTo(models.User, { foreignKey: 'UserId' }) + Like.belongsTo(models.Tweet, { foreignKey: 'TweetId' }) + } + } + 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 b826a1018..2a29a7156 100644 --- a/models/reply.js +++ b/models/reply.js @@ -1,6 +1,30 @@ '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) { + Reply.belongsTo(models.User, { foreignKey: 'UserId' }) + Reply.belongsTo(models.Tweet, { foreignKey: 'TweetId' }) + } + } + Reply.init( + { + UserId: DataTypes.INTEGER, + TweetId: DataTypes.INTEGER, + comment: DataTypes.TEXT, + deletedAt: DataTypes.DATE + }, + { + sequelize, + modelName: 'Reply', + tableName: 'Replies', + underscored: true + } + ) return Reply } diff --git a/models/tweet.js b/models/tweet.js index a8b660077..c89ddea7f 100644 --- a/models/tweet.js +++ b/models/tweet.js @@ -1,8 +1,30 @@ -'use strict'; +'use strict' +const { Model } = require('sequelize') module.exports = (sequelize, DataTypes) => { - const Tweet = sequelize.define('Tweet', { - }, {}); - Tweet.associate = function(models) { - }; - return Tweet; -}; \ No newline at end of file + 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) { + Tweet.hasMany(models.Reply, { foreignKey: 'TweetId' }) + Tweet.hasMany(models.Like, { foreignKey: 'TweetId' }) + Tweet.belongsTo(models.User, { foreignKey: 'UserId' }) + } + } + Tweet.init( + { + UserId: DataTypes.INTEGER, + description: DataTypes.TEXT, + deletedAt: DataTypes.DATE + }, + { + sequelize, + modelName: 'Tweet', + tableName: 'Tweets', + underscored: true + } + ) + return Tweet +} diff --git a/models/user.js b/models/user.js index 82c5f84c8..9d6f1a328 100644 --- a/models/user.js +++ b/models/user.js @@ -1,8 +1,46 @@ -'use strict'; +'use strict' +const { Model } = require('sequelize') module.exports = (sequelize, DataTypes) => { - const User = sequelize.define('User', { - }, {}); - User.associate = function(models) { - }; - return User; -}; \ No newline at end of file + 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) { + User.hasMany(models.Reply, { foreignKey: 'UserId' }) + User.hasMany(models.Tweet, { foreignKey: 'UserId' }) + User.hasMany(models.Like, { foreignKey: 'UserId' }) + User.belongsToMany(User, { + through: models.Followship, + foreignKey: 'followingId', + as: 'Followers' + }) + User.belongsToMany(User, { + through: models.Followship, + foreignKey: 'followerId', + as: 'Followings' + }) + } + } + User.init( + { + email: DataTypes.STRING, + password: DataTypes.STRING, + name: DataTypes.STRING, + account: DataTypes.STRING, + cover: DataTypes.STRING, + avatar: DataTypes.STRING, + introduction: DataTypes.TEXT, + role: DataTypes.STRING, + deletedAt: DataTypes.DATE + }, + { + sequelize, + modelName: 'User', + tableName: 'Users', + underscored: true + } + ) + return User +} From 124e16a71aaf5f85b5ea82004c298b285f40b33e Mon Sep 17 00:00:00 2001 From: Suz033 Date: Sun, 4 Jun 2023 16:54:59 +0800 Subject: [PATCH 005/232] fix: modify {{{ body }}} position --- views/index.hbs | 0 views/layouts/main.hbs | 7 +++---- 2 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 views/index.hbs diff --git a/views/index.hbs b/views/index.hbs new file mode 100644 index 000000000..e69de29bb diff --git a/views/layouts/main.hbs b/views/layouts/main.hbs index ddaf324c1..aeaf31972 100644 --- a/views/layouts/main.hbs +++ b/views/layouts/main.hbs @@ -29,6 +29,9 @@
  • 首頁

    + + {{{ body }}} +
@@ -41,10 +44,6 @@ - - {{{ body }}} - - {{!-- bootstrap --}} From 35b45d1e58efe13e17d57492f562e4ba029ce70d Mon Sep 17 00:00:00 2001 From: shaochenn Date: Sun, 4 Jun 2023 21:56:28 +0800 Subject: [PATCH 006/232] feat: add tweets view --- app.js | 2 +- package-lock.json | 5 --- public/stylesheets/style.css | 62 +++++++++++++++++++++++++++ views/index.hbs | 0 views/layouts/main.hbs | 11 +++-- views/tweets.hbs | 81 ++++++++++++++++++++++++++++++++++++ 6 files changed, 151 insertions(+), 10 deletions(-) create mode 100644 views/index.hbs create mode 100644 views/tweets.hbs diff --git a/app.js b/app.js index eafec81f5..881b079fe 100644 --- a/app.js +++ b/app.js @@ -16,7 +16,7 @@ app.set('view engine', 'hbs') // use helpers.ensureAuthenticated(req) to replace req.isAuthenticated() // routes -app.get('/', (req, res) => res.render('index')) +app.get('/', (req, res) => res.render('tweets')) app.listen(port, () => console.log(`Example app listening on port ${port}!`)) // exports diff --git a/package-lock.json b/package-lock.json index 8fbfb6417..1b0bc0cca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -153,11 +153,6 @@ "unpipe": "1.0.0" } }, - "bootstrap": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", - "integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==" - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index a7ad0a210..e899c832c 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -216,4 +216,66 @@ body { font-weight: 500; font-size: 14px; color: #92929D; +} + +.tweet-btn { + width: 64px; + height: 40px; +} + +.tweet-placeholder { + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 700; + font-size: 18px; + line-height: 26px; + + color: #6C757D; +} + +.tweet-close-button { + background: transparent; + border: none; +} + +#description::placeholder { + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 400; + font-size: 16px; + line-height: 26px; + color: #6C757D; +} + +.tweet-text { + margin-left: 8px; + margin-right: 3px; + width: 528px; +} + +.tweet-name { + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 700; + font-size: 16px; + line-height: 26px; + color: #171725; +} + +.tweet-account { + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 22px; + color: #6C757D; +} + +.tweet-description { + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 400; + font-size: 16px; + line-height: 26px; + color: #171725; } \ No newline at end of file diff --git a/views/index.hbs b/views/index.hbs new file mode 100644 index 000000000..e69de29bb diff --git a/views/layouts/main.hbs b/views/layouts/main.hbs index ddaf324c1..feae1fff7 100644 --- a/views/layouts/main.hbs +++ b/views/layouts/main.hbs @@ -16,6 +16,12 @@ {{!-- css --}} + {{!-- google fonts --}} + + + @@ -30,6 +36,7 @@
  • 首頁

  • + {{{body}}} @@ -41,10 +48,6 @@ - - {{{ body }}} - - {{!-- bootstrap --}} diff --git a/views/tweets.hbs b/views/tweets.hbs new file mode 100644 index 000000000..453de4386 --- /dev/null +++ b/views/tweets.hbs @@ -0,0 +1,81 @@ +
  • + + 有什麼新鮮事? +
    推文
    +
  • + + +
  • +
    +
    + +
    +
    + Apple + +

    Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

    +
    +
    +
  • + +
  • +
    +
    + +
    +
    + Apple + +

    Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

    +
    +
    +
  • + +
  • +
    +
    + +
    +
    + Apple + +

    Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

    +
    +
    +
  • + + + + + + + + \ No newline at end of file From 51ece8f1ce71d526308a0a0914e42cd5b17da77f Mon Sep 17 00:00:00 2001 From: shaochenn Date: Mon, 5 Jun 2023 09:54:17 +0800 Subject: [PATCH 007/232] view: add tweets-list like/reply icon --- public/stylesheets/style.css | 19 +++++++++++++------ views/layouts/main.hbs | 6 +++++- views/tweets.hbs | 16 +++++++++++++--- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index e899c832c..1247cb072 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -228,8 +228,6 @@ body { font-style: normal; font-weight: 700; font-size: 18px; - line-height: 26px; - color: #6C757D; } @@ -243,7 +241,6 @@ body { font-style: normal; font-weight: 400; font-size: 16px; - line-height: 26px; color: #6C757D; } @@ -258,7 +255,6 @@ body { font-style: normal; font-weight: 700; font-size: 16px; - line-height: 26px; color: #171725; } @@ -267,7 +263,6 @@ body { font-style: normal; font-weight: 400; font-size: 14px; - line-height: 22px; color: #6C757D; } @@ -276,6 +271,18 @@ body { font-style: normal; font-weight: 400; font-size: 16px; - line-height: 26px; color: #171725; +} + +.tweets-icon { + width: 16px; + height: 16px; +} + +.tweets-interact-counts { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 600; + font-size: 14px; + color: #6C757D; } \ No newline at end of file diff --git a/views/layouts/main.hbs b/views/layouts/main.hbs index feae1fff7..11003e881 100644 --- a/views/layouts/main.hbs +++ b/views/layouts/main.hbs @@ -17,11 +17,15 @@ {{!-- google fonts --}} - + {{!-- --}} + + diff --git a/views/tweets.hbs b/views/tweets.hbs index 453de4386..5428c3150 100644 --- a/views/tweets.hbs +++ b/views/tweets.hbs @@ -14,6 +14,10 @@ Apple

    Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

    + + 13 + + 76 @@ -27,6 +31,10 @@ Apple

    Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

    + + 13 + + 76 @@ -40,15 +48,17 @@ Apple

    Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

    + + 13 + + 76 + - - - \ No newline at end of file From f54a4c2d0d0d35749590a05ba7a71191a81605f6 Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 7 Jun 2023 13:20:35 +0800 Subject: [PATCH 049/232] feat: add user individul information --- controllers/profile-controller.js | 46 +++++++++++++++++++++++++++---- routes/index.js | 8 +++--- views/partials/user-profile.hbs | 4 +-- views/users/profile.hbs | 32 +++++++++++++++------ 4 files changed, 70 insertions(+), 20 deletions(-) diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index cfc3eb6f8..9a773be85 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -1,10 +1,46 @@ +const helpers = require('../_helpers') +const { User, Followship, Tweet } = require('../models') + const profileController = { - getUserTweets: (req, res) => { + getUserTweets: async (req, res, next) => { // 取得loginUser(使用helpers), userId - // 取對應的user資料 - // 判斷user是否存在 - // 判斷user是否為本人 - res.render('users/profile') + const loginUser = helpers.getUser(req) + const userId = req.params.userId + try { + // 取對應的user資料,包含following跟follower的count + const [user, FollowingsCount, FollowersCount, tweets] = await Promise.all([ + User.findByPk(userId), + // 計算user的folowing數量 + Followship.count({ + where: { followerId: userId } + }), + // 計算user的folower數量 + Followship.count({ + where: { followingId: userId } + }), + // 推文及推文數 + Tweet.findAndCountAll({ + raw: true, + where: { UserId: userId } + }) + ]) + // 判斷user是否存在,沒有就err + if (!user) throw new Error('該用戶不存在!') + // 變數存,user是否為使用者 + const isLoginUser = user.id === loginUser.id + // 將變數加入 + const userData = { + ...user.toJSON(), + FollowingsCount, + FollowersCount, + tweetsCount: tweets.count, + isLoginUser + } + // render + res.render('users/profile', { user: userData, tweets: tweets.rows }) + } catch (err) { + next(err) + } }, getUserFollows: (req, res) => { res.render('users/follow') diff --git a/routes/index.js b/routes/index.js index 531724eae..cbadda998 100644 --- a/routes/index.js +++ b/routes/index.js @@ -23,10 +23,10 @@ router.post( router.get('/tweets', authenticated, (req, res) => res.render('index')) -router.get('/users/:id/tweets', authenticated, profileController.getUserTweets) -router.get('/users/:id/followings', authenticated, profileController.getUserFollows) -router.get('/users/:id/followers', authenticated, profileController.getUserFollows) -router.get('/users/:id', authenticated, profileController.editUser) +router.get('/users/:userId/tweets', authenticated, profileController.getUserTweets) +router.get('/users/:userId/followings', authenticated, profileController.getUserFollows) +router.get('/users/:userId/followers', authenticated, profileController.getUserFollows) +router.get('/users/:userId', authenticated, profileController.editUser) router.use('/', (req, res) => res.redirect('/tweets')) diff --git a/views/partials/user-profile.hbs b/views/partials/user-profile.hbs index f3fe5d432..03e3bc08c 100644 --- a/views/partials/user-profile.hbs +++ b/views/partials/user-profile.hbs @@ -5,7 +5,7 @@ -
    John Doe
    -

    25 推文

    +
    {{user.name}}
    +

    {{user.tweetsCount}} 推文

    \ No newline at end of file diff --git a/views/users/profile.hbs b/views/users/profile.hbs index 157351273..3474d3cb1 100644 --- a/views/users/profile.hbs +++ b/views/users/profile.hbs @@ -9,16 +9,30 @@ {{> user-profile}}
    cover - avatar -
    -
    編輯個人資料
    -
    + avatar + {{#if user.isLoginUser}} +
    +
    編輯個人資料
    +
    + {{else}} +
    + + mail + + + + +
    + +
    +
    + {{/if}}
    -
    John Doe
    -

    @heyjohn

    -

    Amet minim mollit non deserunt ullamco est sit aliqua dolor do amet sint.

    - 34 個跟隨中 - 59 位跟隨者 +
    {{user.name}}
    +

    @{{user.account}}

    +

    {{user.introduction}}

    + {{user.FollowingsCount}} 個跟隨中 + {{user.FollowersCount}} 位跟隨者
    \ No newline at end of file + + +
    + cover + avatar + {{#if user.isLoginUser}} +
    +
    編輯個人資料
    +
    + {{else}} +
    + + mail + + + + +
    + +
    +
    + {{/if}} +
    +
    {{user.name}}
    +

    @{{user.account}}

    +

    {{user.introduction}}

    + {{user.FollowingsCount}} 個跟隨中 + {{user.FollowersCount}} 位跟隨者 +
    + +
    + + + \ No newline at end of file diff --git a/views/users/follow.hbs b/views/users/follow.hbs index 84f171b8a..76c1f06dd 100644 --- a/views/users/follow.hbs +++ b/views/users/follow.hbs @@ -1,67 +1,89 @@ -
    - {{> user-profile}} - - +
    + {{! recommend-followings }} + {{> recommend-followings}} \ No newline at end of file diff --git a/views/users/likes.hbs b/views/users/likes.hbs new file mode 100644 index 000000000..c2f5057cb --- /dev/null +++ b/views/users/likes.hbs @@ -0,0 +1,105 @@ +
    + {{! navbar }} + {{> navbar}} + + {{!tweet-list }} +
    +
      +
      + {{> user-profile route = 'likes'}} + + +
        +
      • +
        +
        + +
        +
        + Apple + +
        + 回覆 + +
        +

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum + dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        + +
        +
        +
        +
      • +
      • +
        +
        + +
        +
        + Apple + +
        + 回覆 + +
        +

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum + dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        + +
        +
        +
        +
      • +
      • +
        +
        + +
        +
        + Apple + +
        + 回覆 + +
        +

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum + dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        + +
        +
        +
        +
      • +
      +
      +
    +
    + + {{! recommend-followings }} + {{> recommend-followings}} + +
    \ No newline at end of file diff --git a/views/users/profile.hbs b/views/users/profile.hbs deleted file mode 100644 index 3474d3cb1..000000000 --- a/views/users/profile.hbs +++ /dev/null @@ -1,185 +0,0 @@ -
    - {{! navbar }} - {{> navbar}} - - {{!tweet-list }} -
    -
      -
      - {{> user-profile}} -
      - cover - avatar - {{#if user.isLoginUser}} -
      -
      編輯個人資料
      -
      - {{else}} -
      - - mail - - - - -
      - -
      -
      - {{/if}} -
      -
      {{user.name}}
      -

      @{{user.account}}

      -

      {{user.introduction}}

      - {{user.FollowingsCount}} 個跟隨中 - {{user.FollowersCount}} 位跟隨者 -
      - -
      - -
        -
      • -
        -
        - -
        -
        - Apple - -
        - 回覆 - -
        -

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco - cillum dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        - -
        -
        -
        -
      • -
      • -
        -
        - -
        -
        - Apple - -
        - 回覆 - -
        -

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco - cillum dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        - -
        -
        -
        -
      • -
      • -
        -
        - -
        -
        - Apple - -
        - 回覆 - -
        -

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco - cillum dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        - -
        -
        -
        -
      • -
      - -
      - - - - -
    -
    - - {{! recommend-followings }} - {{> recommend-followings}} - -
    \ No newline at end of file diff --git a/views/users/replies.hbs b/views/users/replies.hbs new file mode 100644 index 000000000..e62533e82 --- /dev/null +++ b/views/users/replies.hbs @@ -0,0 +1,105 @@ +
    + {{! navbar }} + {{> navbar}} + + {{!tweet-list }} +
    +
      +
      + {{> user-profile route = 'replies'}} + + +
        +
      • +
        +
        + +
        +
        + Apple + +
        + 回覆 + +
        +

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum + dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        + +
        +
        +
        +
      • +
      • +
        +
        + +
        +
        + Apple + +
        + 回覆 + +
        +

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum + dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        + +
        +
        +
        +
      • +
      • +
        +
        + +
        +
        + Apple + +
        + 回覆 + +
        +

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum + dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        + +
        +
        +
        +
      • +
      +
      +
    +
    + + {{! recommend-followings }} + {{> recommend-followings}} + +
    \ No newline at end of file diff --git a/views/users/tweets.hbs b/views/users/tweets.hbs new file mode 100644 index 000000000..c1c6b581e --- /dev/null +++ b/views/users/tweets.hbs @@ -0,0 +1,105 @@ +
    + {{! navbar }} + {{> navbar}} + + {{!tweet-list }} +
    +
      +
      + {{> user-profile route = 'tweets'}} + + +
        +
      • +
        +
        + +
        +
        + Apple + +
        + 回覆 + +
        +

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum + dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        + +
        +
        +
        +
      • +
      • +
        +
        + +
        +
        + Apple + +
        + 回覆 + +
        +

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum + dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        + +
        +
        +
        +
      • +
      • +
        +
        + +
        +
        + Apple + +
        + 回覆 + +
        +

        Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum + dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

        + +
        +
        +
        +
      • +
      +
      +
    +
    + + {{! recommend-followings }} + {{> recommend-followings}} + +
    \ No newline at end of file From 4064c81494c7af2bb065a190c1e1f2a65669442b Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 7 Jun 2023 15:22:59 +0800 Subject: [PATCH 051/232] feat: add tweets list --- controllers/profile-controller.js | 51 +++++++++++++++++---- routes/index.js | 2 +- views/partials/user-profile.hbs | 6 +-- views/users/tweets.hbs | 74 ++++--------------------------- 4 files changed, 54 insertions(+), 79 deletions(-) diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index 9b6db8ddb..985c36a8e 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -1,15 +1,17 @@ +const Sequelize = require('sequelize') + const helpers = require('../_helpers') -const { User, Followship, Tweet } = require('../models') +const { User, Followship, Tweet, Reply, Like } = require('../models') +const { group } = require('console') const profileController = { - getUserTweets: async (req, res, next) => { + getUser: async (req, res, next) => { // 取得loginUser(使用helpers), userId const loginUser = helpers.getUser(req) const userId = req.params.userId - const route = 'tweets' try { // 取對應的user資料,包含following跟follower的count - const [user, FollowingsCount, FollowersCount, tweets] = await Promise.all([ + const [user, FollowingsCount, FollowersCount, tweetsCount] = await Promise.all([ User.findByPk(userId), // 計算user的folowing數量 Followship.count({ @@ -20,8 +22,7 @@ const profileController = { where: { followingId: userId } }), // 推文及推文數 - Tweet.findAndCountAll({ - raw: true, + Tweet.count({ where: { UserId: userId } }) ]) @@ -30,15 +31,47 @@ const profileController = { // 變數存,user是否為使用者 const isLoginUser = user.id === loginUser.id // 將變數加入 - const userData = { + req.userData = { ...user.toJSON(), FollowingsCount, FollowersCount, - tweetsCount: tweets.count, + tweetsCount, isLoginUser } + // next + next() + } catch (err) { + next(err) + } + }, + getUserTweets: async (req, res, next) => { + const { userData } = req + // 取得 id + const userId = req.params.userId + try { + // tweets找相對應的資料,跟user關聯,依照建立時間排列 + // replies、likes數量計算 + const tweets = await Tweet.findAll({ + attributes: { + include: [ + [Sequelize.fn('COUNT', Sequelize.col('Replies.id')), 'repliesCount'], + [Sequelize.fn('COUNT', Sequelize.col('Likes.id')), 'likesCount'] + ] + }, + where: { UserId: userId }, + include: [ + User, + // 不要引入reply資料 + { model: Reply, attributes: [] }, + { model: Like, attributes: [] } + ], + order: [['createdAt', 'DESC']], + group: ['Tweet.id'] + }) + // 整理資料 + const tweetsData = tweets.map(tweet => tweet.toJSON()) // render - res.render('users/tweets', { user: userData, tweets: tweets.rows, route }) + res.render('users/tweets', { user: userData, tweets: tweetsData }) } catch (err) { next(err) } diff --git a/routes/index.js b/routes/index.js index cbadda998..555b167f9 100644 --- a/routes/index.js +++ b/routes/index.js @@ -23,7 +23,7 @@ router.post( router.get('/tweets', authenticated, (req, res) => res.render('index')) -router.get('/users/:userId/tweets', authenticated, profileController.getUserTweets) +router.get('/users/:userId/tweets', authenticated, profileController.getUser, profileController.getUserTweets) router.get('/users/:userId/followings', authenticated, profileController.getUserFollows) router.get('/users/:userId/followers', authenticated, profileController.getUserFollows) router.get('/users/:userId', authenticated, profileController.editUser) diff --git a/views/partials/user-profile.hbs b/views/partials/user-profile.hbs index 35fe51583..ecc4d08f9 100644 --- a/views/partials/user-profile.hbs +++ b/views/partials/user-profile.hbs @@ -39,13 +39,13 @@ diff --git a/views/users/tweets.hbs b/views/users/tweets.hbs index c1c6b581e..c09ed2379 100644 --- a/views/users/tweets.hbs +++ b/views/users/tweets.hbs @@ -10,90 +10,32 @@
      + {{#each tweets}}
    • - Apple - -
      - 回覆 - -
      -

      Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum - dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

      - -
      -
      -
      -
    • -
    • -
      -
      - -
      -
      - Apple - -
      - 回覆 - -
      -

      Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum - dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

      - -
      -
      -
      -
    • -
    • -
      -
      - -
      -
      - Apple - -
      - 回覆 - -
      -

      Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum - dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

      + {{this.User.name}} + + +

      {{this.description}}


    • + {{/each}}
    From cfa1a0fce050a450a90c46be50efba07674f8ed1 Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 7 Jun 2023 15:54:36 +0800 Subject: [PATCH 052/232] feat: modify require helpers --- app.js | 6 +- middleware/auth.js | 10 +- routes/index.js | 5 +- test/requests/user.spec.js | 281 +++++++++++++++++-------------------- 4 files changed, 141 insertions(+), 161 deletions(-) diff --git a/app.js b/app.js index 59815bde3..742a45b5b 100644 --- a/app.js +++ b/app.js @@ -8,7 +8,7 @@ const passport = require('./config/passport') const handlebarsHelpers = require('./helpers/handlebars-helpers') // files -const helpers = require('./_helpers') +const { getUser, ensureAuthenticated } = require('./_helpers') const routes = require('./routes') app.use(express.static('public')) @@ -37,8 +37,8 @@ app.use((req, res, next) => { res.locals.success_messages = req.flash('success_messages') res.locals.error_messages = req.flash('error_messages') // 為了不跟user的資料衝突,所以更換名字 - res.locals.loginUser = helpers.getUser(req) - res.locals.isAuthenticated = helpers.ensureAuthenticated(req) + res.locals.loginUser = getUser(req) + res.locals.isAuthenticated = ensureAuthenticated(req) next() }) diff --git a/middleware/auth.js b/middleware/auth.js index d687adc11..00d9dbc42 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -1,8 +1,8 @@ -const { ensureAuthenticated, getUser } = require('../_helpers') +const helpers = require('../_helpers') const authenticated = (req, res, next) => { - const isUser = getUser(req)?.role === 'user' - if (ensureAuthenticated(req)) { + const isUser = helpers.getUser(req)?.role === 'user' + if (helpers.ensureAuthenticated(req)) { if (isUser) { return next() } @@ -15,8 +15,8 @@ const authenticated = (req, res, next) => { } const adminAuthenticated = (req, res, next) => { - if (ensureAuthenticated(req)) { - if (getUser(req).role === 'admin') { + if (helpers.ensureAuthenticated(req)) { + if (helpers.getUser(req).role === 'admin') { return next() } req.flash('error_messages', '帳號或密碼錯誤!') diff --git a/routes/index.js b/routes/index.js index 555b167f9..c7a9a7b79 100644 --- a/routes/index.js +++ b/routes/index.js @@ -28,7 +28,10 @@ router.get('/users/:userId/followings', authenticated, profileController.getUser router.get('/users/:userId/followers', authenticated, profileController.getUserFollows) router.get('/users/:userId', authenticated, profileController.editUser) -router.use('/', (req, res) => res.redirect('/tweets')) +router.use('/', (req, res) => { + console.log('404') + res.redirect('/tweets') +}) router.use('/', generalErrorHandler) diff --git a/test/requests/user.spec.js b/test/requests/user.spec.js index f287598ef..55c3cfa65 100644 --- a/test/requests/user.spec.js +++ b/test/requests/user.spec.js @@ -2,7 +2,7 @@ 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 db = require('../../models') @@ -19,308 +19,285 @@ const db = require('../../models') describe('# user request', () => { context('# tweets', () => { - before(async() => { + before(async () => { // 模擬登入資料 - this.ensureAuthenticated = sinon.stub( - helpers, 'ensureAuthenticated' - ).returns(true); - this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + this.ensureAuthenticated = sinon.stub(helpers, 'ensureAuthenticated').returns(true) + this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1, Followings: [], role: 'user' }) // 確保清除了測試資料庫中的 User, Tweet 資料 - 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 }) // 在測試資料庫中,新增 mock 資料 await db.User.create({}) await db.User.create({}) - await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet'}) - await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet'}) + await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet' }) + await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet' }) }) // 可以瀏覽自己的貼文頁面 describe('go to current_user page', () => { - it('will show current users tweets', (done) => { + it('will show current users tweets', done => { // 送出 GET /users/1/tweets request(app) .get('/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) // 檢查是否含有標題 User1 的 Tweet 內容 res.text.should.include('User1 的 Tweet') - return done(); - }); + return done() + }) }) }) // 可以瀏覽其他人的貼文頁面 describe('go to other user page', () => { - it('will show other users tweets', (done) => { + it('will show other users tweets', done => { // 送出 GET /users/2/tweets request(app) .get('/users/2/tweets') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); - // 檢查是否含有標題 User2 的 Tweet 內容 + .end(function (err, res) { + if (err) return done(err) + // 檢查是否含有標題 User2 的 Tweet 內容 res.text.should.include('User2 的 Tweet') - return done(); - }); + return done() + }) }) }) after(async () => { // 清除登入及測試資料庫資料 - this.ensureAuthenticated.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.ensureAuthenticated.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('# edit', () => { - before(async() => { + before(async () => { // 模擬登入資料 - this.ensureAuthenticated = sinon.stub( - helpers, 'ensureAuthenticated' - ).returns(true); - this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + this.ensureAuthenticated = sinon.stub(helpers, 'ensureAuthenticated').returns(true) + this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({name: 'User1'}) - await db.User.create({name: 'User2'}) + await db.User.create({ name: 'User1' }) + await db.User.create({ name: 'User2' }) }) - + // 可以瀏覽編輯使用者頁面 describe('go to edit page', () => { - it('will render edit page', (done) => { + it('will render edit page', done => { // 送出 request GET /api/users/1 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) // 檢查是否成功取得 User1 的內容 - res.body.name.should.equal('User1'); - return done(); - }); + res.body.name.should.equal('User1') + return done() + }) }) // 不可瀏覽編輯他人的頁面 - it('will redirect if not this user', (done) => { + it('will redirect if not this user', done => { // 送出 request GET /api/users/2 request(app) .get('/api/users/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) // 檢查是否有出現 error 內容 - res.body.status.should.equal('error'); - return done(); - }); + res.body.status.should.equal('error') + return done() + }) }) }) after(async () => { - // 清除登入及測試資料庫資料 - this.ensureAuthenticated.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.ensureAuthenticated.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('#update', () => { - before(async() => { + before(async () => { // 模擬登入資料 - this.ensureAuthenticated = sinon.stub( - helpers, 'ensureAuthenticated' - ).returns(true); - this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + this.ensureAuthenticated = sinon.stub(helpers, 'ensureAuthenticated').returns(true) + this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 await db.User.create({}) }) // 可以更新使用者的資訊 describe('successfully update', () => { - it('will change users intro', (done) => { + it('will change users intro', done => { // 送出 request POST /api/users/1 request(app) .post('/api/users/1') .send('name=abc') .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 => { // 確認資料是否更新成 abc - user.name.should.equal('abc'); - return done(); + user.name.should.equal('abc') + return done() }) - }); + }) }) }) after(async () => { - // 清除登入及測試資料庫資料 - this.ensureAuthenticated.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.ensureAuthenticated.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('#followings #followers', () => { - before(async() => { + before(async () => { // 模擬登入資料 - this.ensureAuthenticated = sinon.stub( - helpers, 'ensureAuthenticated' - ).returns(true); - this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + this.ensureAuthenticated = sinon.stub(helpers, 'ensureAuthenticated').returns(true) + this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 - await db.User.create({name: 'User1'}) - await db.User.create({name: 'User2'}) - await db.User.create({name: 'User3'}) + await db.User.create({ name: 'User1' }) + await db.User.create({ name: 'User2' }) + await db.User.create({ name: 'User3' }) - const date = new Date(); - await db.Followship.create({followerId: 1, followingId: 2}) - await db.Followship.create({followerId: 1, followingId: 3}) - await db.Followship.create({followerId: 2, followingId: 1}) - await db.Followship.create({followerId: 3, followingId: 1}) + const date = new Date() + await db.Followship.create({ followerId: 1, followingId: 2 }) + await db.Followship.create({ followerId: 1, followingId: 3 }) + await db.Followship.create({ followerId: 2, followingId: 1 }) + await db.Followship.create({ followerId: 3, followingId: 1 }) }) // 可以顯示所有追蹤的人的資訊 describe('go to followings page', () => { - it('will show all followings users', (done) => { + it('will show all followings users', done => { // 送出 request GET /users/1/followings request(app) .get('/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) // 檢查是否含有 User2 的資訊 res.text.should.include('User2') - return done(); - }); + return done() + }) }) // 追蹤者資訊依據新增時間排序 - it('followings list ordered by desc', (done) => { + it('followings list ordered by desc', done => { // 送出 request GET /users/1/followings request(app) .get('/users/1/followings') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); - // 檢查 User3 是否在 User2 的前面 + .end(function (err, res) { + if (err) return done(err) + // 檢查 User3 是否在 User2 的前面 res.text.indexOf('User3').should.above(res.text.indexOf('User2')) - return done(); - }); + return done() + }) }) }) - + // 可以顯示所有被追蹤的資訊 describe('go to followers page', () => { - it('can see followers on other user page', (done) => { - // 送出 request GET /users/1/followers + it('can see followers on other user page', done => { + // 送出 request GET /users/1/followers request(app) .get('/users/1/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) // 檢查 User1 是否有被 User3 追蹤 res.text.should.include('User3') - return done(); - }); + return done() + }) }) // 追蹤者資訊依據新增時間排序 - it('followers list ordered by desc', (done) => { - // 送出 request GET /users/1/followers + it('followers list ordered by desc', done => { + // 送出 request GET /users/1/followers request(app) .get('/users/1/followers') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); - // 檢查 User3 是否在 User2 的前面 + .end(function (err, res) { + if (err) return done(err) + // 檢查 User3 是否在 User2 的前面 res.text.indexOf('User3').should.above(res.text.indexOf('User2')) - return done(); - }); + return done() + }) }) }) after(async () => { - // 清除登入及測試資料庫資料 - this.ensureAuthenticated.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.ensureAuthenticated.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('#likes', () => { - before(async() => { + before(async () => { // 模擬登入資料 - this.ensureAuthenticated = sinon.stub( - helpers, 'ensureAuthenticated' - ).returns(true); - this.getUser = sinon.stub( - helpers, 'getUser' - ).returns({id: 1, Followings: [], role: 'user'}); + this.ensureAuthenticated = sinon.stub(helpers, 'ensureAuthenticated').returns(true) + this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1, Followings: [], role: 'user' }) // 在測試資料庫中,新增 mock 資料 await db.User.create({}) - await db.Tweet.create({UserId: 1, description: 'Tweet1'}) - await db.Like.create({UserId: 1, TweetId: 1}) + await db.Tweet.create({ UserId: 1, description: 'Tweet1' }) + await db.Like.create({ UserId: 1, TweetId: 1 }) }) describe('go to likes page', () => { - it('show users like tweets', (done) => { - // 送出 request GET /users/1/likes + it('show users like tweets', done => { + // 送出 request GET /users/1/likes request(app) .get('/users/1/likes') .set('Accept', 'application/json') .expect(200) - .end(function(err, res) { - if (err) return done(err); + .end(function (err, res) { + if (err) return done(err) // 檢查是否喜愛的貼文裡有 Tweet1 res.text.should.include('Tweet1') - return done(); - }); + return done() + }) }) }) after(async () => { - // 清除登入及測試資料庫資料 - this.ensureAuthenticated.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.ensureAuthenticated.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 }) }) }) -}); +}) From c6fe8273561ccd7387c1776f1daf41b7c9f86df7 Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 7 Jun 2023 16:42:46 +0800 Subject: [PATCH 053/232] feat: add replies list --- controllers/profile-controller.js | 36 +++++++++++- routes/index.js | 7 +-- views/partials/user-profile.hbs | 2 +- views/users/replies.hbs | 98 ++++++------------------------- 4 files changed, 56 insertions(+), 87 deletions(-) diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index 985c36a8e..b29746d72 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -33,6 +33,8 @@ const profileController = { // 將變數加入 req.userData = { ...user.toJSON(), + cover: user.cover || '/images/profile/cover.png', + avatar: user.avatar || '/images/profile/avatar.png', FollowingsCount, FollowersCount, tweetsCount, @@ -76,8 +78,40 @@ const profileController = { next(err) } }, + getUserReplies: async (req, res, next) => { + const { userData } = req + // 取得userId + const userId = req.params.userId + try { + // 取得reply資料及回覆的推文者 + const replies = await Reply.findAll({ + where: { UserId: userId }, + include: [ + { + model: Tweet, + include: [ + // 只取回覆的推文者 + { model: User, attributes: ['account'] } + ], + // 不能是空的 + attributes: ['id'] + } + ] + }) + // 整理資料 + const repliesData = replies.map(reply => reply.toJSON()) + console.log(userData) + // render + res.render('users/replies', { user: userData, replies: repliesData }) + } catch (err) { + next(err) + } + }, + getUserLikes: (req, res) => { + res.render('users/likes', { user: userData }) + }, getUserFollows: (req, res) => { - res.render('users/follow') + res.render('users/likes') }, editUser: (req, res) => { res.render('users/edit') diff --git a/routes/index.js b/routes/index.js index c7a9a7b79..4f5062b78 100644 --- a/routes/index.js +++ b/routes/index.js @@ -24,14 +24,13 @@ router.post( router.get('/tweets', authenticated, (req, res) => res.render('index')) router.get('/users/:userId/tweets', authenticated, profileController.getUser, profileController.getUserTweets) +router.get('/users/:userId/replies', authenticated, profileController.getUser, profileController.getUserReplies) +router.get('/users/:userId/likes', authenticated, profileController.getUser, profileController.getUserLikes) router.get('/users/:userId/followings', authenticated, profileController.getUserFollows) router.get('/users/:userId/followers', authenticated, profileController.getUserFollows) router.get('/users/:userId', authenticated, profileController.editUser) -router.use('/', (req, res) => { - console.log('404') - res.redirect('/tweets') -}) +router.use('/', (req, res) => res.redirect('/tweets')) router.use('/', generalErrorHandler) diff --git a/views/partials/user-profile.hbs b/views/partials/user-profile.hbs index ecc4d08f9..1d6be2912 100644 --- a/views/partials/user-profile.hbs +++ b/views/partials/user-profile.hbs @@ -11,7 +11,7 @@
    - cover + cover avatar {{#if user.isLoginUser}}
    diff --git a/views/users/replies.hbs b/views/users/replies.hbs index e62533e82..17858c337 100644 --- a/views/users/replies.hbs +++ b/views/users/replies.hbs @@ -10,90 +10,26 @@
      -
    • -
      -
      - -
      -
      - Apple - -
      - 回覆 - -
      -

      Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum - dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

      - -
      -
      -
      -
    • -
    • -
      -
      - -
      -
      - Apple - -
      - 回覆 - -
      -

      Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum - dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

      - -
      -
      -
      -
    • -
    • -
      -
      - -
      -
      - Apple - -
      - 回覆 - + {{#each replies}} +
    • +
      +
      +
      -

      Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum - dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

      -
      - - reply - 76 - - +
      + {{../user.name}} + + +
      + 回覆 + +
      +

      {{this.comment}}

      -
      -
      -
    • +
      + + {{/each}}
    From 3bfdd7f79d5b5c45248f6c7e3c08ce760c660a28 Mon Sep 17 00:00:00 2001 From: vinchiengithub Date: Wed, 7 Jun 2023 18:37:24 +0800 Subject: [PATCH 054/232] fix: fix img src --- views/signin.hbs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/views/signin.hbs b/views/signin.hbs index 095578d57..670e97310 100644 --- a/views/signin.hbs +++ b/views/signin.hbs @@ -1,6 +1,6 @@
    - +

    登入 Alphitter

    @@ -32,8 +32,10 @@ autofocus />
    - +
    + +
    -
    + \ No newline at end of file From da5d0d8922e75fc3f7955a78f151b93290665e82 Mon Sep 17 00:00:00 2001 From: Suz033 Date: Wed, 7 Jun 2023 19:38:58 +0800 Subject: [PATCH 055/232] feat: add declaration file for module --- modules.d.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 modules.d.ts diff --git a/modules.d.ts b/modules.d.ts new file mode 100644 index 000000000..057ea41bc --- /dev/null +++ b/modules.d.ts @@ -0,0 +1,2 @@ +declare module 'faker' +declare module 'bcrypt-nodejs' \ No newline at end of file From 697dc578638916d003b4176381a52fdf63175622 Mon Sep 17 00:00:00 2001 From: Suz033 Date: Wed, 7 Jun 2023 19:39:51 +0800 Subject: [PATCH 056/232] feat: add tweets seeder --- package-lock.json | 15 +++++++++++--- package.json | 3 ++- seeders/20230607110802-tweets-seed-file.js | 23 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 seeders/20230607110802-tweets-seed-file.js diff --git a/package-lock.json b/package-lock.json index 9225500b4..58e9d8cf0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -149,6 +149,15 @@ "@types/ms": "*" } }, + "@types/faker": { + "version": "6.6.9", + "resolved": "https://registry.npmjs.org/@types/faker/-/faker-6.6.9.tgz", + "integrity": "sha512-Y9YYm5L//8ooiiknO++4Gr539zzdI0j3aXnOBjo1Vk+kTvffY10GuE2wn78AFPECwZ5MYGTjiDVw1naLLdDimw==", + "dev": true, + "requires": { + "faker": "*" + } + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1880,9 +1889,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", diff --git a/package.json b/package.json index 132aadd66..697522f26 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "express": "^4.16.4", "express-handlebars": "^3.0.0", "express-session": "^1.15.6", - "faker": "^4.1.0", + "faker": "^5.5.3", "method-override": "^3.0.0", "mocha": "^6.0.2", "mysql2": "^1.6.4", @@ -32,6 +32,7 @@ }, "devDependencies": { "@types/bcrypt-nodejs": "0.0.31", + "@types/faker": "^6.6.9", "eslint": "^7.32.0", "eslint-config-standard": "^16.0.3", "eslint-plugin-import": "^2.23.4", diff --git a/seeders/20230607110802-tweets-seed-file.js b/seeders/20230607110802-tweets-seed-file.js new file mode 100644 index 000000000..4bd2cf4d7 --- /dev/null +++ b/seeders/20230607110802-tweets-seed-file.js @@ -0,0 +1,23 @@ +'use strict' + +const faker = require('faker') + +module.exports = { + up: async (queryInterface, Sequelize) => { + const users = await queryInterface.sequelize.query( + 'SELECT id FROM Users;', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + await queryInterface.bulkInsert('Tweets', + Array.from({ length: 50 }, () => ({ + user_id: users[Math.floor(Math.random() * users.length)].id, + description: faker.lorem.text(), + created_at: new Date(), + updated_at: new Date() + })) + ) + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Tweets', {}) + } +} From 01bc030171b8fb7f7a4e5d4c639b1cdbc2834c89 Mon Sep 17 00:00:00 2001 From: Suz033 Date: Wed, 7 Jun 2023 19:57:03 +0800 Subject: [PATCH 057/232] feat: add replies seeder --- seeders/20230607115306-replies-seed-file.js | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 seeders/20230607115306-replies-seed-file.js diff --git a/seeders/20230607115306-replies-seed-file.js b/seeders/20230607115306-replies-seed-file.js new file mode 100644 index 000000000..3cc313091 --- /dev/null +++ b/seeders/20230607115306-replies-seed-file.js @@ -0,0 +1,28 @@ +'use strict' + +const faker = require('faker') + +module.exports = { + up: async (queryInterface, Sequelize) => { + const users = await queryInterface.sequelize.query( + 'SELECT id FROM Users;', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + const tweets = await queryInterface.sequelize.query( + 'SELECT id FROM Tweets;', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + await queryInterface.bulkInsert('Replies', + Array.from({ length: 50 }, () => ({ + user_id: users[Math.floor(Math.random() * users.length)].id, + tweet_id: tweets[Math.floor(Math.random() * tweets.length)].id, + comment: faker.lorem.text(), + created_at: new Date(), + updated_at: new Date() + })) + ) + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Replies', {}) + } +} From 0c68b3e850bb15c65d7f56e29cb5125499a6eba3 Mon Sep 17 00:00:00 2001 From: Suz033 Date: Wed, 7 Jun 2023 20:13:17 +0800 Subject: [PATCH 058/232] feat: add likes seeder --- seeders/20230607115741-likes-seed-file.js | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 seeders/20230607115741-likes-seed-file.js diff --git a/seeders/20230607115741-likes-seed-file.js b/seeders/20230607115741-likes-seed-file.js new file mode 100644 index 000000000..6dea49dc9 --- /dev/null +++ b/seeders/20230607115741-likes-seed-file.js @@ -0,0 +1,25 @@ +'use strict' + +module.exports = { + up: async (queryInterface, Sequelize) => { + const users = await queryInterface.sequelize.query( + 'SELECT id FROM Users;', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + const tweets = await queryInterface.sequelize.query( + 'SELECT id FROM Tweets;', + { type: queryInterface.sequelize.QueryTypes.SELECT } + ) + await queryInterface.bulkInsert('Replies', + Array.from({ length: 50 }, () => ({ + user_id: users[Math.floor(Math.random() * users.length)].id, + tweet_id: tweets[Math.floor(Math.random() * tweets.length)].id, + created_at: new Date(), + updated_at: new Date() + })) + ) + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Replies', {}) + } +} From 538e5ad1ca41d40b72e185d4df4a3f2c110013b3 Mon Sep 17 00:00:00 2001 From: vinchiengithub Date: Wed, 7 Jun 2023 20:20:03 +0800 Subject: [PATCH 059/232] feat: modify routes & adminController --- app.js | 7 ++----- controllers/admin-controller.js | 14 +++++++++++++- controllers/user-controller.js | 8 ++++++++ middleware/auth.js | 4 ++-- routes/index.js | 19 +++++++++++++++++++ 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/app.js b/app.js index 965d063c0..e46502e7f 100644 --- a/app.js +++ b/app.js @@ -42,11 +42,8 @@ app.use((req, res, next) => { }) // routes -app.get('/', (req, res) => res.render('index')) -app.get('/signin', (req, res) => res.render('signin')); -app.get('/signup', (req, res) => res.render('signup')); -app.get('/admin/signin', (req, res) => res.render('admin/signin')); -app.get('/admin/tweets', (req, res) => res.render('admin/tweets')); +app.use(routes) + app.listen(port, () => console.log(`Example app listening on port ${port}!`)) // exports diff --git a/controllers/admin-controller.js b/controllers/admin-controller.js index 76eeedc27..e246e1d1b 100644 --- a/controllers/admin-controller.js +++ b/controllers/admin-controller.js @@ -1,3 +1,15 @@ -const adminController = {} +const adminController = { + adminSigninPage: (req, res) => { + res.render('admin/signin') + }, + adminTweetsPage: (req, res) => { + res.render('admin/tweets') + }, + adminSignin: (req, res, next) => { + console.log(req.user) + req.flash('success_messages', '成功登入!') + res.redirect('admin/tweets') + } +} module.exports = adminController diff --git a/controllers/user-controller.js b/controllers/user-controller.js index 2d993ff1a..a8eafc912 100644 --- a/controllers/user-controller.js +++ b/controllers/user-controller.js @@ -2,10 +2,18 @@ const userController = { signinPage: (req, res) => { res.render('signin') }, + signupPage: (req, res) => { + res.render('signup') + }, signin: (req, res, next) => { console.log(req.user) req.flash('success_messages', '成功登入!') res.redirect('/tweets') + }, + signup: (req, res, next) => { + console.log(req.user) + req.flash('success_messages', '註冊成功,請登入!') + res.redirect('/signin') } } diff --git a/middleware/auth.js b/middleware/auth.js index d687adc11..8c6b00b62 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -20,10 +20,10 @@ const adminAuthenticated = (req, res, next) => { return next() } req.flash('error_messages', '帳號或密碼錯誤!') - return res.redirect('/signin') + return res.redirect('/admin/signin') } else { req.flash('error_messages', '請先登入!') - return res.redirect('/signin') + return res.redirect('/admin/signin') } } diff --git a/routes/index.js b/routes/index.js index f46409d07..114f9e7f1 100644 --- a/routes/index.js +++ b/routes/index.js @@ -10,6 +10,7 @@ const tweetsController = require('../controllers/tweets-controller') const { authenticated, adminAuthenticated } = require('../middleware/auth') +// signin router.get('/signin', userController.signinPage) router.post( '/signin', @@ -20,6 +21,24 @@ router.post( userController.signin ) +// signup +router.get('/signup', userController.signupPage) +router.post( + '/signup', + passport.authenticate('local', { + failureRedirect: '/signup', + failureFlash: true + }), + userController.signup +) + +// admin +router.get('/admin/signin', adminController.adminSigninPage) +router.get('/admin/tweets', adminAuthenticated, (req, res) => + res.render('admin/tweets') +) + +// index router.get('/tweets', authenticated, (req, res) => res.render('index')) router.get('/users/:id/tweets', profileController.getUserTweets) From 1acdb10ca00bf50fbbd08a878df8ed35c277a6ca Mon Sep 17 00:00:00 2001 From: shaochenn Date: Wed, 7 Jun 2023 21:09:50 +0800 Subject: [PATCH 060/232] add tweets router --- .eslintignore | 2 +- controllers/tweets-controller.js | 4 ++-- models/index.js | 40 ++++++++++++++++---------------- routes/index.js | 2 -- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/.eslintignore b/.eslintignore index ceaa7dc6e..1d80413c6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,2 @@ /node_modules/* -/tests/* \ No newline at end of file +/test/* \ No newline at end of file diff --git a/controllers/tweets-controller.js b/controllers/tweets-controller.js index 242fdbab0..f362e6c8c 100644 --- a/controllers/tweets-controller.js +++ b/controllers/tweets-controller.js @@ -1,9 +1,9 @@ const tweetsController = { getTweets: (req, res, next) => { - res.render('tweets') + return res.render('tweets') }, getTweet: (req, res, next) => { - res.render('tweet') + return res.render('tweet') } } diff --git a/models/index.js b/models/index.js index 33f09e776..427848cb0 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(path.resolve(__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/routes/index.js b/routes/index.js index 521e8b9a8..57f204d31 100644 --- a/routes/index.js +++ b/routes/index.js @@ -20,8 +20,6 @@ router.post( userController.signin ) -//router.get('/tweets', authenticated, (req, res) => res.render('index')) - router.get('/users/:id/tweets', profileController.getUserTweets) router.get('/users/:id/followings', profileController.getUserFollows) router.get('/users/:id/followers', profileController.getUserFollows) From acc2baab521f16cd161535cb08140371dcc48d87 Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 7 Jun 2023 21:12:57 +0800 Subject: [PATCH 061/232] feat: add likes list --- controllers/profile-controller.js | 43 +++++++++++++++-- views/users/likes.hbs | 76 ++++--------------------------- 2 files changed, 49 insertions(+), 70 deletions(-) diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index b29746d72..aa7ca2c86 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -100,15 +100,52 @@ const profileController = { }) // 整理資料 const repliesData = replies.map(reply => reply.toJSON()) - console.log(userData) // render res.render('users/replies', { user: userData, replies: repliesData }) } catch (err) { next(err) } }, - getUserLikes: (req, res) => { - res.render('users/likes', { user: userData }) + getUserLikes: async (req, res, next) => { + const { userData } = req + const userId = req.params.userId + try { + // likes找相對應的資料,跟user推文者關聯,依照like建立時間排列 + const likes = await Like.findAll({ + where: { UserId: userId }, + include: [Tweet], + order: [['createdAt', 'DESC']] + }) + // 透過likeId找對應的tweet資料 + // replies、likes數量計算 + const tweets = await Promise.all( + likes.map(like => { + console.log(like) + return Tweet.findByPk(like.TweetId, { + attributes: { + include: [ + [Sequelize.fn('COUNT', Sequelize.col('Replies.id')), 'repliesCount'], + [Sequelize.fn('COUNT', Sequelize.col('Likes.id')), 'likesCount'] + ] + }, + where: { UserId: userId }, + include: [ + User, + // 不要引入reply資料 + { model: Reply, attributes: [] }, + { model: Like, attributes: ['createdAt'] } + ], + group: ['Tweet.id'] + }) + }) + ) + // 整理資料 + const tweetsData = tweets.map(tweet => tweet.toJSON()) + // render + res.render('users/likes', { user: userData, tweets: tweetsData }) + } catch (err) { + next(err) + } }, getUserFollows: (req, res) => { res.render('users/likes') diff --git a/views/users/likes.hbs b/views/users/likes.hbs index c2f5057cb..c61229894 100644 --- a/views/users/likes.hbs +++ b/views/users/likes.hbs @@ -10,90 +10,32 @@
      + {{#each tweets}}
    • - Apple - -
      - 回覆 - -
      -

      Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum - dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

      - -
      -
      -
      -
    • -
    • -
      -
      - -
      -
      - Apple - -
      - 回覆 - -
      -

      Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum - dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

      - -
      -
      -
      -
    • -
    • -
      -
      - -
      -
      - Apple - -
      - 回覆 - -
      -

      Nulla Lorem mollit cupidatat irure. Laborum magna nulla duis ullamco cillum - dolor. Voluptate exercitation incididunt aliquip deserunt reprehenderit elit laborum.

      + {{this.User.name}} + + +

      {{this.description}}


    • + {{/each}}
    From e3c639a8d4fa47afbdbef899fd8c8ba5893cf483 Mon Sep 17 00:00:00 2001 From: vinchiengithub Date: Wed, 7 Jun 2023 21:38:43 +0800 Subject: [PATCH 062/232] feat: add admin-users page --- controllers/admin-controller.js | 4 +++- controllers/user-controller.js | 2 -- routes/index.js | 5 ++--- views/admin/tweets.hbs | 2 +- views/admin/users.hbs | 5 +++++ views/partials/admin-navbar.hbs | 4 ++-- views/partials/admin-users.hbs | 32 ++++++++++++++++++++++++++++++++ 7 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 views/admin/users.hbs create mode 100644 views/partials/admin-users.hbs diff --git a/controllers/admin-controller.js b/controllers/admin-controller.js index e246e1d1b..29995dad0 100644 --- a/controllers/admin-controller.js +++ b/controllers/admin-controller.js @@ -5,8 +5,10 @@ const adminController = { adminTweetsPage: (req, res) => { res.render('admin/tweets') }, + adminUsersPage: (req, res) => { + res.render('admin/users') + }, adminSignin: (req, res, next) => { - console.log(req.user) req.flash('success_messages', '成功登入!') res.redirect('admin/tweets') } diff --git a/controllers/user-controller.js b/controllers/user-controller.js index a8eafc912..8bad97890 100644 --- a/controllers/user-controller.js +++ b/controllers/user-controller.js @@ -6,12 +6,10 @@ const userController = { res.render('signup') }, signin: (req, res, next) => { - console.log(req.user) req.flash('success_messages', '成功登入!') res.redirect('/tweets') }, signup: (req, res, next) => { - console.log(req.user) req.flash('success_messages', '註冊成功,請登入!') res.redirect('/signin') } diff --git a/routes/index.js b/routes/index.js index 114f9e7f1..12b727752 100644 --- a/routes/index.js +++ b/routes/index.js @@ -34,9 +34,8 @@ router.post( // admin router.get('/admin/signin', adminController.adminSigninPage) -router.get('/admin/tweets', adminAuthenticated, (req, res) => - res.render('admin/tweets') -) +router.get('/admin/tweets', adminController.adminTweetsPage) +router.get('/admin/users', adminController.adminUsersPage) // index router.get('/tweets', authenticated, (req, res) => res.render('index')) diff --git a/views/admin/tweets.hbs b/views/admin/tweets.hbs index 06fba12c3..09171b372 100644 --- a/views/admin/tweets.hbs +++ b/views/admin/tweets.hbs @@ -1,5 +1,5 @@
    {{!-- admin-nvabar --}} - {{> admin-navbar}} + {{> admin-navbar route='tweets'}} {{> admin-tweets}}
    \ No newline at end of file diff --git a/views/admin/users.hbs b/views/admin/users.hbs new file mode 100644 index 000000000..1071a0958 --- /dev/null +++ b/views/admin/users.hbs @@ -0,0 +1,5 @@ +
    + {{!-- admin-nvabar --}} + {{> admin-navbar route='users'}} + {{> admin-users}} +
    \ No newline at end of file diff --git a/views/partials/admin-navbar.hbs b/views/partials/admin-navbar.hbs index 80933e72c..01efc97ea 100644 --- a/views/partials/admin-navbar.hbs +++ b/views/partials/admin-navbar.hbs @@ -5,13 +5,13 @@ -
    - +
    +
    diff --git a/views/signin.hbs b/views/signin.hbs index 670e97310..ea6d05895 100644 --- a/views/signin.hbs +++ b/views/signin.hbs @@ -32,7 +32,7 @@ autofocus />
    -
    +
    From fe4ed0748bf8c639ce3679fa48f2f8447f7ec050 Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 7 Jun 2023 22:07:50 +0800 Subject: [PATCH 064/232] feat: add followings list --- controllers/profile-controller.js | 30 +++++++- routes/index.js | 4 +- views/partials/user-profile.hbs | 4 +- views/users/{follow.hbs => followers.hbs} | 0 views/users/followings.hbs | 90 +++++++++++++++++++++++ 5 files changed, 122 insertions(+), 6 deletions(-) rename views/users/{follow.hbs => followers.hbs} (100%) create mode 100644 views/users/followings.hbs diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index aa7ca2c86..bd63fed74 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -147,8 +147,34 @@ const profileController = { next(err) } }, - getUserFollows: (req, res) => { - res.render('users/likes') + getUserFollowings: async (req, res, next) => { + const userId = req.params.userId + // 判斷active + const followings = true + try { + // 取對應的user資料、包含追隨的人、推文數 + const [user, tweetsCount] = await Promise.all([ + User.findByPk(userId, { + include: [{ model: User, as: 'Followings' }] + }), + Tweet.count({ + where: { UserId: userId } + }) + ]) + // 判斷user是否存在,沒有就err + if (!user) throw new Error('該用戶不存在!') + const userData = { + ...user.toJSON(), + tweetsCount + } + console.log(userData) + res.render('users/followings', { user: userData, followings }) + } catch (err) { + next(err) + } + }, + getUserFollowers: (req, res) => { + res.render('users/followers') }, editUser: (req, res) => { res.render('users/edit') diff --git a/routes/index.js b/routes/index.js index 4f5062b78..f4e61299a 100644 --- a/routes/index.js +++ b/routes/index.js @@ -26,8 +26,8 @@ router.get('/tweets', authenticated, (req, res) => res.render('index')) router.get('/users/:userId/tweets', authenticated, profileController.getUser, profileController.getUserTweets) router.get('/users/:userId/replies', authenticated, profileController.getUser, profileController.getUserReplies) router.get('/users/:userId/likes', authenticated, profileController.getUser, profileController.getUserLikes) -router.get('/users/:userId/followings', authenticated, profileController.getUserFollows) -router.get('/users/:userId/followers', authenticated, profileController.getUserFollows) +router.get('/users/:userId/followings', authenticated, profileController.getUserFollowings) +router.get('/users/:userId/followers', authenticated, profileController.getUserFollowers) router.get('/users/:userId', authenticated, profileController.editUser) router.use('/', (req, res) => res.redirect('/tweets')) diff --git a/views/partials/user-profile.hbs b/views/partials/user-profile.hbs index 1d6be2912..d8c3e40ac 100644 --- a/views/partials/user-profile.hbs +++ b/views/partials/user-profile.hbs @@ -34,8 +34,8 @@
    {{user.name}}

    @{{user.account}}

    {{user.introduction}}

    - {{user.FollowingsCount}} 個
    跟隨中 - {{user.FollowersCount}} 位跟隨者 + {{user.FollowingsCount}} 個跟隨中 + {{user.FollowersCount}} 位跟隨者
    From 01c24d15dd80585d6fb9bfadaac10fe7e4b6fe47 Mon Sep 17 00:00:00 2001 From: shaochenn Date: Thu, 8 Jun 2023 01:50:21 +0800 Subject: [PATCH 068/232] feature:formate relative time --- controllers/tweets-controller.js | 1 - helpers/handlebars-helpers.js | 25 +++++++++++++++++++++- seeders/20230606163450-users-seed-file.js | 10 ++++----- seeders/20230607144425-tweets-seed-file.js | 2 +- views/tweets.hbs | 2 +- 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/controllers/tweets-controller.js b/controllers/tweets-controller.js index b58c01d74..93b27ebb1 100644 --- a/controllers/tweets-controller.js +++ b/controllers/tweets-controller.js @@ -15,7 +15,6 @@ const tweetsController = { nest: true }) ]) - console.log(tweets) res.render('tweets', { user, tweets }) } catch (err) { next(err) diff --git a/helpers/handlebars-helpers.js b/helpers/handlebars-helpers.js index 919a159bb..a4cc88feb 100644 --- a/helpers/handlebars-helpers.js +++ b/helpers/handlebars-helpers.js @@ -1,12 +1,35 @@ // modules const dayjs = require('dayjs') const relativeTime = require('dayjs/plugin/relativeTime') -dayjs.extend(relativeTime) +dayjs.extend(relativeTime) // exports module.exports = { currentYear: () => dayjs().year(), relativeTimeFromNow: a => dayjs(a).fromNow(), + formatRelativeTime: targetTime => { + const currentTime = dayjs() + if ((currentTime - targetTime) < 0) { + console.log(currentTime) + return '-' + } + const diffInMilliseconds = (currentTime - targetTime) + const second = Math.floor(diffInMilliseconds / 1000) + const minutes = Math.floor(diffInMilliseconds / 60000) + const hours = Math.floor(minutes / 60) + + if (second < 60) { + return `${second} 秒` + } else if (minutes < 60) { + return `${minutes} 分鐘` + } else if (hours < 24) { + return `${hours} 小時` + } else if (dayjs(targetTime).year() === dayjs().year()) { + return dayjs(targetTime).format('M月D日') + } else { + return dayjs(targetTime).format('YYYY年M月D日') + } + }, ifCond: function (a, b, options) { return a === b ? options.fn(this) : options.inverse(this) } diff --git a/seeders/20230606163450-users-seed-file.js b/seeders/20230606163450-users-seed-file.js index f1581274c..874dc058e 100644 --- a/seeders/20230606163450-users-seed-file.js +++ b/seeders/20230606163450-users-seed-file.js @@ -22,7 +22,7 @@ module.exports = { avatar: `https://loremflickr.com/140/140/avatar/?lock=${ Math.random() * 100 }`, - cover:`https://loremflickr.com/640/200/landscape/?lock=${ + cover: `https://loremflickr.com/640/200/landscape/?lock=${ Math.random() * 100 }`, introduction: faker.lorem.text(), @@ -38,7 +38,7 @@ module.exports = { avatar: `https://loremflickr.com/140/140/avatar/?lock=${ Math.random() * 100 }`, - cover:`https://loremflickr.com/640/200/landscape/?lock=${ + cover: `https://loremflickr.com/640/200/landscape/?lock=${ Math.random() * 100 }`, introduction: faker.lorem.text(), @@ -54,7 +54,7 @@ module.exports = { avatar: `https://loremflickr.com/140/140/avatar/?lock=${ Math.random() * 100 }`, - cover:`https://loremflickr.com/640/200/landscape/?lock=${ + cover: `https://loremflickr.com/640/200/landscape/?lock=${ Math.random() * 100 }`, introduction: faker.lorem.text(), @@ -70,7 +70,7 @@ module.exports = { avatar: `https://loremflickr.com/140/140/avatar/?lock=${ Math.random() * 100 }`, - cover:`https://loremflickr.com/640/200/landscape/?lock=${ + cover: `https://loremflickr.com/640/200/landscape/?lock=${ Math.random() * 100 }`, introduction: faker.lorem.text(), @@ -86,7 +86,7 @@ module.exports = { avatar: `https://loremflickr.com/140/140/avatar/?lock=${ Math.random() * 100 }`, - cover:`https://loremflickr.com/640/200/landscape/?lock=${ + cover: `https://loremflickr.com/640/200/landscape/?lock=${ Math.random() * 100 }`, introduction: faker.lorem.text(), diff --git a/seeders/20230607144425-tweets-seed-file.js b/seeders/20230607144425-tweets-seed-file.js index 8459ff6c9..4bd2cf4d7 100644 --- a/seeders/20230607144425-tweets-seed-file.js +++ b/seeders/20230607144425-tweets-seed-file.js @@ -20,4 +20,4 @@ module.exports = { down: async (queryInterface, Sequelize) => { await queryInterface.bulkDelete('Tweets', {}) } -} \ No newline at end of file +} diff --git a/views/tweets.hbs b/views/tweets.hbs index 040270fda..6f26d0252 100644 --- a/views/tweets.hbs +++ b/views/tweets.hbs @@ -30,7 +30,7 @@
    {{this.User.name}}
    - +

    {{this.description}}

    From 1da02826455990083338a1f83c22691047568dce Mon Sep 17 00:00:00 2001 From: alvin Date: Thu, 8 Jun 2023 12:35:37 +0800 Subject: [PATCH 069/232] feat: add edit account --- app.js | 3 + controllers/profile-controller.js | 81 ++++++++++++--- helpers/handlebars-helpers.js | 2 + public/stylesheets/style.css | 98 +++++++++--------- routes/index.js | 3 +- views/partials/navbar.hbs | 2 +- views/users/edit.hbs | 158 ++++++++++++++++-------------- 7 files changed, 213 insertions(+), 134 deletions(-) diff --git a/app.js b/app.js index 742a45b5b..cb0c9c1ac 100644 --- a/app.js +++ b/app.js @@ -4,6 +4,7 @@ const app = express() const handlebars = require('express-handlebars') const session = require('express-session') const flash = require('connect-flash') +const methodOverride = require('method-override') const passport = require('./config/passport') const handlebarsHelpers = require('./helpers/handlebars-helpers') @@ -33,6 +34,8 @@ app.use(flash()) app.use(passport.initialize()) app.use(passport.session()) +app.use(methodOverride('_method')) + app.use((req, res, next) => { res.locals.success_messages = req.flash('success_messages') res.locals.error_messages = req.flash('error_messages') diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index d298513a7..86b4132c7 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -1,5 +1,5 @@ const Sequelize = require('sequelize') - +const bcrypt = require('bcryptjs') const helpers = require('../_helpers') const { User, Followship, Tweet, Reply, Like } = require('../models') const { group } = require('console') @@ -8,7 +8,7 @@ const profileController = { getUser: async (req, res, next) => { // 取得loginUser(使用helpers), userId const loginUser = helpers.getUser(req) - const userId = req.params.userId + const { userId } = req.params try { // 取對應的user資料,包含following跟follower的count const [user, FollowingsCount, FollowersCount, tweetsCount] = await Promise.all([ @@ -49,7 +49,7 @@ const profileController = { getUserTweets: async (req, res, next) => { const { userData } = req // 取得 id - const userId = req.params.userId + const { userId } = req.params try { // tweets找相對應的資料,跟user關聯,依照建立時間排列 // replies、likes數量計算 @@ -81,7 +81,7 @@ const profileController = { getUserReplies: async (req, res, next) => { const { userData } = req // 取得userId - const userId = req.params.userId + const { userId } = req.params try { // 取得reply資料及回覆的推文者 const replies = await Reply.findAll({ @@ -108,7 +108,7 @@ const profileController = { }, getUserLikes: async (req, res, next) => { const { userData } = req - const userId = req.params.userId + const { userId } = req.params try { // likes找相對應的資料,跟user推文者關聯,依照like建立時間排列 const likes = await Like.findAll({ @@ -120,7 +120,6 @@ const profileController = { // replies、likes數量計算 const tweets = await Promise.all( likes.map(like => { - console.log(like) return Tweet.findByPk(like.TweetId, { attributes: { include: [ @@ -148,7 +147,7 @@ const profileController = { } }, getUserFollowings: async (req, res, next) => { - const userId = req.params.userId + const { userId } = req.params // 判斷active const followings = true try { @@ -174,7 +173,7 @@ const profileController = { }, getUserFollowers: async (req, res, next) => { const loginUser = helpers.getUser(req) - const userId = req.params.userId + const { userId } = req.params // 判斷active const followers = true try { @@ -206,19 +205,77 @@ const profileController = { // 追隨者的id對應到user追隨的id isFollowed: user.Followings.some(following => follower.id === following.id) })) - console.log(userFollowersData) const userData = { ...user.toJSON(), tweetsCount } - console.log(userData) res.render('users/followers', { user: userData, followers, userFollowers: userFollowersData }) } catch (err) { next(err) } }, - editUser: (req, res) => { - res.render('users/edit') + editUserAccount: async (req, res, next) => { + // 抓id + const { userId } = req.params + const loginUser = helpers.getUser(req) + // 判斷是否為本人 + if (loginUser.id !== Number(userId)) return res.redirect('back') + try { + // 找對應user、取出帳號、名稱、信箱 + const user = await User.findByPk(userId, { + raw: true, + attributes: ['id', 'account', 'name', 'email'] + }) + // 找不到就報錯 + if (!user) throw new Error('該用戶不存在!') + // render + res.render('users/edit', { user }) + } catch (err) { + next(err) + } + }, + putUserAccount: async (req, res, next) => { + // 抓id, 表單資料 + const { userId } = req.params + const loginUser = helpers.getUser(req) + const { account, name, email, password, passwordCheck } = req.body + const saltNumber = 10 + // 判斷是否為本人 + if (loginUser.id !== Number(userId)) return res.redirect('back') + try { + // 找對應user、找出是否有account、email + const [user, isAccountExist, isEmailExist] = await Promise.all([ + User.findByPk(userId), + User.findOne({ where: { account } }), + User.findOne({ where: { email } }) + ]) + // 找不到就報錯 + if (!user) throw new Error('該用戶不存在!') + // 如果account、email有更動就判斷是否有重複 + if (user.account !== account && isAccountExist) throw new Error('該帳號已存在!') + + if (user.email !== email && isEmailExist) throw new Error('該email已存在!') + // 確認name有無超過50字 + if (name.length > 50) throw new Error('該名字超過字數上限!') + // 確認密碼是否正確 + if (password !== passwordCheck) throw new Error('密碼不一致!') + // 將密碼hash + const salt = bcrypt.genSaltSync(saltNumber) + const hashedPassword = bcrypt.hashSync(password, salt) + // 更新資料 + const userUpdate = await user.update({ + name, + email, + account, + password: hashedPassword + }) + console.log(userUpdate) + req.session.updateDate = userUpdate + // redirect /tweets + res.redirect('/tweets') + } catch (err) { + next(err) + } } } diff --git a/helpers/handlebars-helpers.js b/helpers/handlebars-helpers.js index 919a159bb..2507e5f67 100644 --- a/helpers/handlebars-helpers.js +++ b/helpers/handlebars-helpers.js @@ -1,7 +1,9 @@ // modules const dayjs = require('dayjs') const relativeTime = require('dayjs/plugin/relativeTime') +require('dayjs/locale/zh-cn') dayjs.extend(relativeTime) +dayjs.locale('zh-cn') // exports module.exports = { diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index ab3f7d444..5ff56ea2d 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -57,26 +57,29 @@ h4 { width: 354px; height: 54px; border-radius: 2px; - background-color: #F5F8FA; + background-color: #f5f8fa; } -.account-label,.password-label { +.account-label, +.password-label { margin-bottom: 0; padding: 0 0 0 10px; font-size: 14px; } -.account-input,.password-input { +.account-input, +.password-input { padding-left: 10px; font-size: 16px; - background-color: #F5F8FA; + background-color: #f5f8fa; border: 0; border-bottom: 2px solid #657786; border-radius: 0; } -.account-input::placeholder,.password-input::placeholder { - color: #B5B5BE; +.account-input::placeholder, +.password-input::placeholder { + color: #b5b5be; } .signin-btn { @@ -85,15 +88,13 @@ h4 { font-size: 20px; border: 0; border-radius: 50px; - background-color: #FF6600; + background-color: #ff6600; } -.other-page-btn p{ +.other-page-btn p { width: 354px; } - - /****** nav ******/ .navbar.navbar-vertical { padding: 0; @@ -336,7 +337,7 @@ h4 { } /* profile */ -.user-container>div>span>.tweet { +.user-container > div > span > .tweet { font-family: 'Noto Sans TC'; font-style: normal; font-weight: 500; @@ -358,18 +359,18 @@ h4 { color: #171725; } -.user-container>.card { +.user-container > .card { position: relative; border-radius: 0px; } -.user-container>.card>.cover { +.user-container > .card > .cover { width: 100%; height: 200px; border-radius: 0px; } -.user-container>.card>.avatar { +.user-container > .card > .avatar { position: absolute; height: 140px; top: 124px; @@ -377,7 +378,7 @@ h4 { border-radius: 50%; } -.user-container>.card>div>.at-name { +.user-container > .card > div > .at-name { font-family: 'Noto Sans TC'; font-style: normal; font-weight: 400; @@ -386,8 +387,8 @@ h4 { color: #6c757d; } -.user-container>.card>div>span, -.user-container>.card>div>span>a { +.user-container > .card > div > span, +.user-container > .card > div > span > a { font-family: 'Noto Sans TC'; font-style: normal; font-weight: 400; @@ -397,13 +398,13 @@ h4 { text-decoration: none; } -.user-container>.card>.edit-btn { +.user-container > .card > .edit-btn { display: flex; justify-content: flex-end; width: 100%; } -.user-container>.card>.edit-btn .btn { +.user-container > .card > .edit-btn .btn { width: 128px; margin-top: 16px; margin-right: 16px; @@ -479,11 +480,11 @@ h4 { line-height: 22px; } -.user-container .reply-name>.text { +.user-container .reply-name > .text { color: #6c757d; } -.user-container .reply-name>.account { +.user-container .reply-name > .account { color: #ff6600; } @@ -537,7 +538,7 @@ h4 { padding: 0; } -.user-edit-modal .modal-header>.modal-close { +.user-edit-modal .modal-header > .modal-close { position: absolute; left: 20px; top: 50%; @@ -548,7 +549,7 @@ h4 { width: 15px; } -.user-edit-modal .modal-header>.modal-title { +.user-edit-modal .modal-header > .modal-title { position: absolute; left: 71px; top: 50%; @@ -561,7 +562,7 @@ h4 { color: #1c1c1c; } -.user-edit-modal .modal-header>.btn-edit { +.user-edit-modal .modal-header > .btn-edit { position: absolute; right: 16px; top: 50%; @@ -575,11 +576,11 @@ h4 { padding: 0; } -.user-edit-modal .modal-body>.cover { +.user-edit-modal .modal-body > .cover { position: relative; } -.user-edit-modal .modal-body>.cover>.cover-img { +.user-edit-modal .modal-body > .cover > .cover-img { -webkit-filter: brightness(0.5); filter: brightness(0.5); width: 100%; @@ -587,7 +588,7 @@ h4 { border-radius: 0px; } -.user-edit-modal .modal-body>.cover>.cover-edit { +.user-edit-modal .modal-body > .cover > .cover-edit { position: absolute; top: 0; left: 0; @@ -598,14 +599,14 @@ h4 { height: 100%; } -.user-edit-modal .modal-body>.cover>.cover-edit>.form-control { +.user-edit-modal .modal-body > .cover > .cover-edit > .form-control { top: 0; width: 0; opacity: 0; pointer-events: none; } -.user-edit-modal .modal-body>.cover>.cover-edit>.form-label { +.user-edit-modal .modal-body > .cover > .cover-edit > .form-label { margin: 0; top: 0; left: 0; @@ -613,7 +614,7 @@ h4 { cursor: pointer; } -.user-edit-modal .modal-body>.cover>.cover-edit>.cover-delete { +.user-edit-modal .modal-body > .cover > .cover-edit > .cover-delete { width: 15px; text-align: center; background-color: transparent; @@ -621,7 +622,7 @@ h4 { margin: 0; } -.user-edit-modal .modal-body>.avatar { +.user-edit-modal .modal-body > .avatar { position: absolute; height: 140px; top: 124px; @@ -629,16 +630,16 @@ h4 { border-radius: 50%; } -.user-edit-modal .modal-body>.form-text { +.user-edit-modal .modal-body > .form-text { margin: 80px 16px 0; } -.user-edit-modal .modal-body>.form-text .box { +.user-edit-modal .modal-body > .form-text .box { background: #f5f8fa; border-bottom: 2px solid #657786; } -.user-edit-modal .modal-body>.form-text .form-label { +.user-edit-modal .modal-body > .form-text .form-label { margin: 0; padding: 0; font-family: 'Noto Sans TC'; @@ -649,12 +650,12 @@ h4 { color: #696974; } -.user-edit-modal .modal-body>.form-text .form-control { +.user-edit-modal .modal-body > .form-text .form-control { background-color: transparent; border: 0; } -.user-edit-modal .modal-body>.form-text .text-amount { +.user-edit-modal .modal-body > .form-text .text-amount { text-align: right; font-family: 'Noto Sans TC'; font-style: normal; @@ -690,12 +691,14 @@ h4 { } .user-edit-container .box { + width: 100%; background: #f5f8fa; border-bottom: 2px solid #657786; margin-bottom: 32px; } .user-edit-container .form-label { + width: 100%; margin: 0; padding: 0; font-family: 'Noto Sans TC'; @@ -722,7 +725,7 @@ h4 { font-style: normal; font-weight: 700; font-size: 18px; - color: #6C757D; + color: #6c757d; } .tweet-close-button { @@ -735,7 +738,7 @@ h4 { font-style: normal; font-weight: 400; font-size: 16px; - color: #6C757D; + color: #6c757d; } .tweet-text { @@ -752,12 +755,13 @@ h4 { color: #171725; } -.tweet-account, .reply-tag-text { +.tweet-account, +.reply-tag-text { font-family: 'Noto Sans TC'; font-style: normal; font-weight: 400; font-size: 14px; - color: #6C757D; + color: #6c757d; } .tweet-description { @@ -778,7 +782,7 @@ h4 { font-style: normal; font-weight: 600; font-size: 14px; - color: #6C757D; + color: #6c757d; } .list-header { @@ -809,7 +813,7 @@ h4 { /* 不要框架 */ height: 1px; /* 設定 1px 的高度 */ - background: #E6ECF0; + background: #e6ecf0; /* 讓背景色填滿高度 1px 的元素空間 */ margin: 20px 0; } @@ -828,7 +832,7 @@ h4 { font-style: normal; font-weight: 500; font-size: 19px; - color: #6C757D; + color: #6c757d; margin-right: 24px; } @@ -837,13 +841,13 @@ h4 { font-style: normal; font-weight: 400; font-size: 14px; - color: #FF6600; + color: #ff6600; } .vertical-line { width: 0; - border-left: 1px solid #B5B5BE; - border-right: 1px solid #B5B5BE; + border-left: 1px solid #b5b5be; + border-right: 1px solid #b5b5be; height: 60%; margin: 10px auto 0; -} \ No newline at end of file +} diff --git a/routes/index.js b/routes/index.js index 49aca9436..134f9a8e4 100644 --- a/routes/index.js +++ b/routes/index.js @@ -38,7 +38,8 @@ router.get('/users/:userId/replies', authenticated, profileController.getUser, p router.get('/users/:userId/likes', authenticated, profileController.getUser, profileController.getUserLikes) router.get('/users/:userId/followings', authenticated, profileController.getUserFollowings) router.get('/users/:userId/followers', authenticated, profileController.getUserFollowers) -router.get('/users/:userId', authenticated, profileController.editUser) +router.get('/api/users/:userId', authenticated, profileController.editUserAccount) +router.put('/api/users/:userId', authenticated, profileController.putUserAccount) router.use('/', (req, res) => res.redirect('/tweets')) diff --git a/views/partials/navbar.hbs b/views/partials/navbar.hbs index 54c34565a..fe92b66e2 100644 --- a/views/partials/navbar.hbs +++ b/views/partials/navbar.hbs @@ -19,7 +19,7 @@
    +{{> message}}
    cover avatar {{#if user.isLoginUser}}
    +
    編輯個人資料
    {{else}} @@ -30,6 +32,7 @@
    {{/if}} +
    {{user.name}}

    @{{user.account}}

    @@ -51,41 +54,50 @@
    -

    後台登入

    +{{> message}} From 17544426d68c3ed9191e6572f38929bb6d9b3435 Mon Sep 17 00:00:00 2001 From: alvin Date: Tue, 13 Jun 2023 17:18:47 +0800 Subject: [PATCH 145/232] =?UTF-8?q?feat:=20=E5=B0=87=E8=87=AA=E5=B7=B1?= =?UTF-8?q?=E6=8E=92=E9=99=A4=E6=96=BC=E6=8E=A8=E8=96=A6=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/followship-controller.js | 5 ++++- seeders/20230607144425-followships-seed-file.js | 2 +- views/partials/recommend-followings.hbs | 3 --- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controllers/followship-controller.js b/controllers/followship-controller.js index 0fef283a0..a67ce453d 100644 --- a/controllers/followship-controller.js +++ b/controllers/followship-controller.js @@ -1,6 +1,7 @@ // files const { Followship, User } = require('../models') const helpers = require('../_helpers') +const { Op } = require('sequelize') // controllers const followshipController = { @@ -49,10 +50,11 @@ const followshipController = { .catch(err => next(err)) }, getTopFollowedUsers: (req, res, next) => { + const loginUser = helpers.getUser(req) const topFollowedUsersNumber = 10 return User.findAll({ include: [{ model: User, as: 'Followers' }], - where: { role: 'user' } + where: { role: 'user', id: { [Op.not]: loginUser.id } } }) .then(users => { const result = users @@ -62,6 +64,7 @@ const followshipController = { isFollowed: req.user.Followings.some(f => f.id === user.id) })) .sort((a, b) => b.followerCount - a.followerCount) + console.log(result) req.session.followingData = result.slice(0, topFollowedUsersNumber - 1) return next() }) diff --git a/seeders/20230607144425-followships-seed-file.js b/seeders/20230607144425-followships-seed-file.js index f60228a0b..be0277709 100644 --- a/seeders/20230607144425-followships-seed-file.js +++ b/seeders/20230607144425-followships-seed-file.js @@ -9,7 +9,7 @@ module.exports = { }) await queryInterface.bulkInsert( 'Followships', - Array.from({ length: 50 }, () => ({ + Array.from({ length: 10 }, () => ({ ...doNotFollowSelf(users), created_at: new Date(), updated_at: new Date() diff --git a/views/partials/recommend-followings.hbs b/views/partials/recommend-followings.hbs index 7f6d48e63..1ea472339 100644 --- a/views/partials/recommend-followings.hbs +++ b/views/partials/recommend-followings.hbs @@ -5,8 +5,6 @@ {{#each followingData}} - {{#ifCond ../loginUser.id this.id}} - {{else}}
  • @@ -31,7 +29,6 @@
  • - {{/ifCond}} {{/each}} \ No newline at end of file From 5b33f320a258c1f3ffedf507e6f2f1ecd721dfcc Mon Sep 17 00:00:00 2001 From: shaochenn <91368309+shaochenn@users.noreply.github.com> Date: Tue, 13 Jun 2023 17:23:05 +0800 Subject: [PATCH 146/232] Update followship-controller.js delete console.log() --- controllers/followship-controller.js | 1 - 1 file changed, 1 deletion(-) diff --git a/controllers/followship-controller.js b/controllers/followship-controller.js index a67ce453d..ad53ab534 100644 --- a/controllers/followship-controller.js +++ b/controllers/followship-controller.js @@ -64,7 +64,6 @@ const followshipController = { isFollowed: req.user.Followings.some(f => f.id === user.id) })) .sort((a, b) => b.followerCount - a.followerCount) - console.log(result) req.session.followingData = result.slice(0, topFollowedUsersNumber - 1) return next() }) From 24778d95dd945b2737cdc1238711d3db04d7df25 Mon Sep 17 00:00:00 2001 From: alvin Date: Tue, 13 Jun 2023 18:54:13 +0800 Subject: [PATCH 147/232] =?UTF-8?q?feat:=20=E4=BF=AE=E6=AD=A3=E4=B8=8D?= =?UTF-8?q?=E8=83=BD=E5=8F=96=E6=B6=88=E5=96=9C=E6=AD=A1=E7=9A=84=E6=8E=A8?= =?UTF-8?q?=E6=96=87=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- views/partials/user-likes.hbs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/partials/user-likes.hbs b/views/partials/user-likes.hbs index c412b78ff..404bc34f0 100644 --- a/views/partials/user-likes.hbs +++ b/views/partials/user-likes.hbs @@ -20,7 +20,7 @@ {{this.repliesCount}} - {{#ifCond ../loginUser.id this.id}} + {{#ifCond ../loginUser.id ../user.id}}
    {{this.likesCount}} @@ -28,7 +28,7 @@ {{else}} - {{this.repliesCount}} + {{this.likesCount}} {{/ifCond}} From 128c63bafab007d5918854519a0d077686ede722 Mon Sep 17 00:00:00 2001 From: alvin Date: Tue, 13 Jun 2023 19:15:24 +0800 Subject: [PATCH 148/232] feat: add like function in user-like page --- controllers/profile-controller.js | 4 +++- views/partials/user-likes.hbs | 19 ++++++++++--------- views/partials/user-tweets.hbs | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index 7d114747e..bb2426058 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -145,6 +145,7 @@ const profileController = { }, getUserLikes: async (req, res, next) => { const { userData, followingData } = req.session + const loginUser = helpers.getUser(req) const { userId } = req.params const route = `users/${userId}/likes` // 取得page, limit, offset @@ -170,7 +171,8 @@ const profileController = { const tweetsData = likes.rows.map((like, index) => ({ ...like.Tweet.toJSON(), likesCount: counts[index].likesCount, - repliesCount: counts[index].repliesCount + repliesCount: counts[index].repliesCount, + isLiked: loginUser.Likes.some(l => l.TweetId === like.TweetId) })) // pagination const pagination = getPagination(page, limit, likes.count) diff --git a/views/partials/user-likes.hbs b/views/partials/user-likes.hbs index 404bc34f0..011140fe2 100644 --- a/views/partials/user-likes.hbs +++ b/views/partials/user-likes.hbs @@ -20,17 +20,18 @@ {{this.repliesCount}} - {{#ifCond ../loginUser.id ../user.id}} - - - {{this.likesCount}} - - {{else}} - - + + {{#if this.isLiked }} +
    + +
    + {{else}} +
    + +
    + {{/if}} {{this.likesCount}}
    - {{/ifCond}} diff --git a/views/partials/user-tweets.hbs b/views/partials/user-tweets.hbs index 436ccb3dd..e8983690f 100644 --- a/views/partials/user-tweets.hbs +++ b/views/partials/user-tweets.hbs @@ -22,7 +22,7 @@ {{this.repliesCount}}
    - {{#if isLiked }} + {{#if this.isLiked }}
    From 1acc2a7c7cc97f0cab8a0edf6f5ad73a907745be Mon Sep 17 00:00:00 2001 From: vinchiengithub Date: Tue, 13 Jun 2023 20:06:13 +0800 Subject: [PATCH 149/232] feat: modify deleteTweet --- controllers/admin-controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/admin-controller.js b/controllers/admin-controller.js index a0d58d637..d6e617219 100644 --- a/controllers/admin-controller.js +++ b/controllers/admin-controller.js @@ -61,8 +61,8 @@ const adminController = { Tweet.destroy( { where: { id: tweetId } } ) - .then(user => { - console.log(user) + .then(() => { + res.redirect('/admin/tweets') }) .catch(err => console.log(err)) } From 97728e2fae38acd0cfe2128198694798bbe8b4c7 Mon Sep 17 00:00:00 2001 From: vinchiengithub Date: Tue, 13 Jun 2023 22:18:13 +0800 Subject: [PATCH 150/232] feat: adminGetTweets add slice --- controllers/admin-controller.js | 9 +++++++++ public/stylesheets/style.css | 5 +++-- views/partials/admin-tweets.hbs | 4 ++-- views/partials/admin-users.hbs | 5 +++-- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/controllers/admin-controller.js b/controllers/admin-controller.js index d6e617219..10e30d000 100644 --- a/controllers/admin-controller.js +++ b/controllers/admin-controller.js @@ -31,6 +31,15 @@ const adminController = { tweets = tweets.map(tweet => ({ ...tweet.toJSON() })) + + tweets.forEach(tweet => { + if (tweet.description.length > 50) { + const newText = tweet.description.slice(0, 50) + '...' + delete tweet.description + tweet.description = newText + } + }) + res.render('admin/tweets', { user, tweets: tweets diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 17739831f..0c6fc9b33 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -63,13 +63,14 @@ h4 { .account-label, .password-label { margin-bottom: 0; - padding: 0 0 0 10px; + padding: 5px 0 2px 10px; font-size: 14px; + color: #696974; } .account-input, .password-input { - padding-left: 10px; + padding: 2px 0 5px 10px; font-size: 16px; background-color: #f5f8fa; border: 0; diff --git a/views/partials/admin-tweets.hbs b/views/partials/admin-tweets.hbs index 7aac99fb4..72a6069f8 100644 --- a/views/partials/admin-tweets.hbs +++ b/views/partials/admin-tweets.hbs @@ -7,7 +7,7 @@
    {{#each tweets}}
  • -
    +
    @@ -18,7 +18,7 @@
    -

    {{this.description}}

    +

    {{this.description}}

    diff --git a/views/partials/admin-users.hbs b/views/partials/admin-users.hbs index af7beffdb..c4f663638 100644 --- a/views/partials/admin-users.hbs +++ b/views/partials/admin-users.hbs @@ -7,7 +7,8 @@
  • {{#each users}} -
  • + {{/each}} From deb3f546d9e9ff768082599031cd018533869f35 Mon Sep 17 00:00:00 2001 From: Suz033 Date: Wed, 14 Jun 2023 01:51:08 +0800 Subject: [PATCH 151/232] feat: modify style and few functions --- app.js | 6 +- controllers/admin-controller.js | 17 +- controllers/profile-controller.js | 74 +++-- controllers/tweets-controller.js | 12 +- controllers/user-controller.js | 6 +- helpers/handlebars-helpers.js | 3 + middleware/auth.js | 8 +- public/images/close_white.svg | 3 + public/javascript/edit.js | 56 ++++ public/stylesheets/style.css | 301 ++++++++++++++++-- routes/index.js | 1 - routes/modules/admin.js | 3 + .../20230607144425-followships-seed-file.js | 20 -- .../20230609090000-followships-seed-file.js | 21 -- views/admin/tweets.hbs | 15 +- views/admin/users.hbs | 5 - views/index.hbs | 5 +- views/partials/admin-navbar.hbs | 6 +- views/partials/admin-tweets.hbs | 58 ++-- views/partials/admin-users.hbs | 67 ++-- views/partials/header.hbs | 25 ++ views/partials/message.hbs | 52 ++- views/partials/modal/modal-edit.hbs | 59 ++++ views/partials/modal/modal-reply.hbs | 56 ++++ views/partials/modal/modal-tweet.hbs | 33 ++ views/partials/navbar/navbar-followships.hbs | 8 + views/partials/navbar/navbar-profile.hbs | 13 + views/partials/{ => navbar}/navbar.hbs | 8 +- views/partials/tweet.hbs | 27 +- views/partials/tweets-list-replies.hbs | 42 +++ views/partials/tweets-list.hbs | 58 ++++ views/partials/tweets.hbs | 57 +--- views/partials/user-edit.hbs | 71 +++-- views/partials/user-followers.hbs | 72 ----- views/partials/user-followings.hbs | 49 --- views/partials/user-followships-list.hbs | 20 ++ views/partials/user-followships.hbs | 33 ++ views/partials/user-likes.hbs | 33 -- views/partials/user-profile.hbs | 88 ++--- views/partials/user-tweets.hbs | 32 -- views/{users => test-users}/edit.hbs | 0 views/{users => test-users}/followers.hbs | 0 views/{users => test-users}/followings.hbs | 0 views/{users => test-users}/likes.hbs | 0 views/{users => test-users}/replies.hbs | 0 views/test-users/test-tweet.hbs | 151 +++++++++ views/test-users/test-tweets.hbs | 167 ++++++++++ views/{users => test-users}/tweets.hbs | 0 views/test-users/user-likes.hbs | 37 +++ views/test-users/user-profile.hbs | 43 +++ .../{partials => test-users}/user-replies.hbs | 1 + 51 files changed, 1388 insertions(+), 534 deletions(-) create mode 100644 public/images/close_white.svg create mode 100644 public/javascript/edit.js delete mode 100644 seeders/20230609090000-followships-seed-file.js delete mode 100644 views/admin/users.hbs create mode 100644 views/partials/header.hbs create mode 100644 views/partials/modal/modal-edit.hbs create mode 100644 views/partials/modal/modal-reply.hbs create mode 100644 views/partials/modal/modal-tweet.hbs create mode 100644 views/partials/navbar/navbar-followships.hbs create mode 100644 views/partials/navbar/navbar-profile.hbs rename views/partials/{ => navbar}/navbar.hbs (82%) create mode 100644 views/partials/tweets-list-replies.hbs create mode 100644 views/partials/tweets-list.hbs delete mode 100644 views/partials/user-followers.hbs delete mode 100644 views/partials/user-followings.hbs create mode 100644 views/partials/user-followships-list.hbs create mode 100644 views/partials/user-followships.hbs delete mode 100644 views/partials/user-likes.hbs delete mode 100644 views/partials/user-tweets.hbs rename views/{users => test-users}/edit.hbs (100%) rename views/{users => test-users}/followers.hbs (100%) rename views/{users => test-users}/followings.hbs (100%) rename views/{users => test-users}/likes.hbs (100%) rename views/{users => test-users}/replies.hbs (100%) create mode 100644 views/test-users/test-tweet.hbs create mode 100644 views/test-users/test-tweets.hbs rename views/{users => test-users}/tweets.hbs (100%) create mode 100644 views/test-users/user-likes.hbs create mode 100644 views/test-users/user-profile.hbs rename views/{partials => test-users}/user-replies.hbs (99%) diff --git a/app.js b/app.js index e0417d151..6cde9756d 100644 --- a/app.js +++ b/app.js @@ -12,11 +12,11 @@ const passport = require('./config/passport') // helpers const handlebarsHelpers = require('./helpers/handlebars-helpers') -// const partialHelpers = require('./helpers/partial-helpers') +const partialHelpers = require('./helpers/partial-helpers') const authHelpers = require('./_helpers') const helpers = { ...handlebarsHelpers, - // ...partialHelpers, + ...partialHelpers, ...authHelpers } const previousPage = require('./middleware/previous-page') @@ -54,6 +54,8 @@ app.use(previousPage) app.use((req, res, next) => { res.locals.success_messages = req.flash('success_messages') res.locals.error_messages = req.flash('error_messages') + res.locals.warning_messages = req.flash('warning_messages') + res.locals.info_messages = req.flash('info_messages') // 為了不跟user的資料衝突,所以更換名字 res.locals.loginUser = helpers.getUser(req) res.locals.isAuthenticated = helpers.ensureAuthenticated(req) diff --git a/controllers/admin-controller.js b/controllers/admin-controller.js index a2c9dddfc..8700d4dda 100644 --- a/controllers/admin-controller.js +++ b/controllers/admin-controller.js @@ -9,10 +9,10 @@ const adminController = { res.render('admin/tweets') }, adminUsersPage: (req, res) => { - res.render('admin/users') + res.render('admin/tweets') }, adminSignin: (req, res, next) => { - req.flash('success_messages', '成功登入!') + req.flash('success_messages', '成功登入!') res.redirect('/admin/tweets') }, adminGetTweets: async (req, res, next) => { @@ -31,9 +31,11 @@ const adminController = { tweets = tweets.map(tweet => ({ ...tweet.toJSON() })) + const partialName = 'admin-tweets' res.render('admin/tweets', { user, - tweets: tweets + tweets: tweets, + partialName }) console.log('adminGetTweets') } catch (err) { @@ -52,11 +54,18 @@ const adminController = { order: [['createdAt', 'DESC']] }) ]) - res.render('admin/users', { users }) + const partialName = 'admin-users' + const userPage = true + res.render('admin/tweets', { users, partialName, userPage }) console.log('adminGetUsers') } catch (err) { next(err) } + }, + logout: (req, res) => { + req.flash('success_messages', '登出成功!') + req.logout() + res.redirect('admin/signin') } } diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index 3d961cc7f..4ec730a2d 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -7,6 +7,7 @@ const { getOffset, getPagination } = require('../helpers/pagination-helper') // 推文顯示數量 const DEFAULT_LIMIT = 50 +const nav = 'profile' const profileController = { getUser: async (req, res, next) => { @@ -62,6 +63,7 @@ const profileController = { const page = Number(req.query.page) || 1 const limit = DEFAULT_LIMIT const offset = getOffset(page, limit) + const loginUser = helpers.getUser(req) try { // tweets找相對應的資料,跟user關聯,依照建立時間排列 // replies、likes數量計算 @@ -86,12 +88,16 @@ const profileController = { subQuery: false }) // 整理資料 - const tweetsData = tweets.rows.map(tweet => tweet.toJSON()) + const tweetsData = tweets.rows.map(tweet => ({ + ...tweet.toJSON(), + isLiked: loginUser && loginUser.Likes && loginUser.Likes.some(like => like.TweetId === tweet.id) + })) // pagination const pagination = getPagination(page, limit, tweets.count.length) // render - const partialName = 'user-tweets' - res.render('index', { user: userData, tweets: tweetsData, route, pagination, partialName }) + const partialName = 'user-profile' + const navbar = 'tweets' + res.render('index', { user: userData, tweets: tweetsData, route, pagination, partialName, navbar }) } catch (err) { next(err) } @@ -114,6 +120,7 @@ const profileController = { model: Tweet, include: [ // 只取回覆的推文者 + { model: User, attributes: ['id'] }, { model: User, attributes: ['account'] } ], // 不能是空的 @@ -124,18 +131,24 @@ const profileController = { offset }) // 整理資料 - const repliesData = replies.rows.map(reply => reply.toJSON()) + const repliesData = replies.rows.map(reply => ({ + ...reply.toJSON(), + user: userData + })) // pagination const pagination = getPagination(page, limit, replies.count) // render - const partialName = 'user-replies' - res.render('index', { user: userData, replies: repliesData, route, pagination, partialName }) + const partialName = 'user-profile' + const navbar = 'replies' + const repliesPage = true + res.render('index', { user: userData, replies: repliesData, route, pagination, partialName, repliesPage, navbar }) } catch (err) { next(err) } }, getUserLikes: async (req, res, next) => { - const { userData } = req.session + const { userData, followingData } = req.session + const loginUser = helpers.getUser(req) const { userId } = req.params const route = `users/${userId}/likes` // 取得page, limit, offset @@ -146,39 +159,29 @@ const profileController = { // likes找相對應的資料,跟user推文者關聯,依照like建立時間排列 const likes = await Like.findAndCountAll({ where: { UserId: userId }, - include: [Tweet], + include: [{ model: Tweet, include: [User] }], order: [['createdAt', 'DESC']], limit, offset }) - // 透過likeId找對應的tweet資料 - // replies、likes數量計算 - const tweets = await Promise.all( - likes.rows.map(like => { - return Tweet.findByPk(like.TweetId, { - attributes: { - include: [ - [Sequelize.fn('COUNT', Sequelize.col('Replies.id')), 'repliesCount'], - [Sequelize.fn('COUNT', Sequelize.col('Likes.id')), 'likesCount'] - ] - }, - include: [ - User, - // 不要引入reply資料 - { model: Reply, attributes: [] }, - { model: Like, attributes: ['createdAt'] } - ], - group: ['Tweet.id'] - }) - }) + const counts = await Promise.all( + likes.rows.map(async like => ({ + repliesCount: await Reply.count({ where: { TweetId: like.TweetId } }), + likesCount: await Like.count({ where: { TweetId: like.TweetId } }) + })) ) - // 整理資料 - const tweetsData = tweets.map(tweet => ({ ...tweet?.toJSON() })) + const tweetsData = likes.rows.map((like, index) => ({ + ...like.Tweet.toJSON(), + likesCount: counts[index].likesCount, + repliesCount: counts[index].repliesCount, + isLiked: loginUser.Likes.some(l => l.TweetId === like.TweetId) + })) // pagination const pagination = getPagination(page, limit, likes.count) // render - const partialName = 'user-likes' - res.render('index', { user: userData, tweets: tweetsData, pagination, route, partialName }) + const partialName = 'user-profile' + const navbar = 'likes' + res.render('index', { user: userData, tweets: tweetsData, pagination, route, partialName, nav, followingData, navbar }) } catch (err) { next(err) } @@ -235,8 +238,9 @@ const profileController = { userData.Followings.sort((a, b) => b.isFollowing - a.isFollowing) // pagination const pagination = getPagination(page, limit, followingsCount) - const partialName = 'user-followings' - res.render('index', { user: userData, followings, pagination, route, partialName }) + const partialName = 'user-followships-list' + const followingsPage = true + res.render('index', { user: userData, followings, pagination, route, partialName, followingsPage }) } catch (err) { next(err) } @@ -290,7 +294,7 @@ const profileController = { userData.Followers.sort((a, b) => b.isFollowing - a.isFollowing) // pagination const pagination = getPagination(page, limit, followersCount) - const partialName = 'user-followers' + const partialName = 'user-followships-list' res.render('index', { user: userData, followers, pagination, route, partialName }) } catch (err) { next(err) diff --git a/controllers/tweets-controller.js b/controllers/tweets-controller.js index f8a65af37..c2a1919ec 100644 --- a/controllers/tweets-controller.js +++ b/controllers/tweets-controller.js @@ -10,8 +10,8 @@ const tweetsController = { order: [['createdAt', 'DESC']] }) tweets = tweets.map(tweet => ({ - likeCount: tweet.Likes.length, - replyCount: tweet.Replies.length, + likesCount: tweet.Likes.length, + repliesCount: tweet.Replies.length, ...tweet.toJSON(), isLiked: loginUser && loginUser.Likes && loginUser.Likes.some(like => like.TweetId === tweet.id) })) @@ -32,8 +32,8 @@ const tweetsController = { const tweet = await Tweet.findByPk(tweetId, { include: [User, { model: Like }, { model: Reply, include: User }] }) - const likeCount = tweet.Likes.length - const replyCount = tweet.Replies.length + const likesCount = tweet.Likes.length + const repliesCount = tweet.Replies.length const isLiked = tweet.Likes.some(l => l.dataValues.UserId === user.id) // 按照發文順序顯示 tweet.Replies = tweet.Replies.sort((a, b) => b.createdAt - a.createdAt) @@ -41,8 +41,8 @@ const tweetsController = { res.render('index', { tweet: tweet.toJSON(), user, - likeCount, - replyCount, + likesCount, + repliesCount, isLiked, partialName }) diff --git a/controllers/user-controller.js b/controllers/user-controller.js index 303561786..a3b7b1bbc 100644 --- a/controllers/user-controller.js +++ b/controllers/user-controller.js @@ -10,7 +10,7 @@ const userController = { res.render('signup') }, signin: (req, res) => { - req.flash('success_messages', '成功登入!') + req.flash('success_messages', '成功登入!') res.redirect('/tweets') }, signup: (req, res) => { @@ -23,7 +23,7 @@ const userController = { User.findOne({ where: { account } }) .then(user => { if (user) { - req.flash('error_messages', 'account 已重複註冊!') + req.flash('error_messages', '帳號已重複註冊!') res.redirect('/signup') throw new Error('account already exists!') } @@ -33,7 +33,7 @@ const userController = { User.findOne({ where: { email } }) .then(user => { if (user) { - req.flash('error_messages', 'email 已重複註冊!') + req.flash('error_messages', 'Email 已重複註冊!') res.redirect('/signup') throw new Error('email already exists!') } diff --git a/helpers/handlebars-helpers.js b/helpers/handlebars-helpers.js index c5b60d221..271950f9e 100644 --- a/helpers/handlebars-helpers.js +++ b/helpers/handlebars-helpers.js @@ -42,5 +42,8 @@ module.exports = { }, ifQuery: function (a, b) { return a?.includes('?') ? `${a}&${b}` : `${a}?${b}` + }, + chooseEach: function (condition, options) { + return condition ? options.fn(this) : options.inverse(this) } } diff --git a/middleware/auth.js b/middleware/auth.js index da1758560..0df55c97c 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -6,10 +6,10 @@ const authenticated = (req, res, next) => { if (isUser) { return next() } - req.flash('error_messages', '帳號或密碼錯誤!') + req.flash('error_messages', '帳號或密碼錯誤!') return res.redirect('/signin') } else { - req.flash('error_messages', '請先登入!') + req.flash('warning_messages', '請先登入!') return res.redirect('/signin') } } @@ -19,10 +19,10 @@ const adminAuthenticated = (req, res, next) => { if (helpers.getUser(req).role === 'admin') { return next() } - req.flash('error_messages', '管理者帳號或密碼錯誤!') + req.flash('error_messages', '管理者帳號或密碼錯誤!') return res.redirect('/admin/signin') } else { - req.flash('error_messages', '請先登入管理者帳號!') + req.flash('warning_messages', '請先登入管理者帳號!') return res.redirect('/admin/signin') } } diff --git a/public/images/close_white.svg b/public/images/close_white.svg new file mode 100644 index 000000000..efd39f607 --- /dev/null +++ b/public/images/close_white.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/javascript/edit.js b/public/javascript/edit.js new file mode 100644 index 000000000..f72f53659 --- /dev/null +++ b/public/javascript/edit.js @@ -0,0 +1,56 @@ +const form = document.querySelector('form') +const input = document.querySelectorAll('input') +const button = document.querySelector('.save-btn') + +// 取得完整的URL +const url = window.location.href + +// 使用正則表達式從URL中匹配數字 +const matches = url.match(/\/(\d+)/) + +// 取得匹配結果中的數字 +const userId = matches[1] + +const inputValue = {} +form.addEventListener('input', () => { + input.forEach(item => { + inputValue[item.name] = item.value + }) +}) + +button.addEventListener('click', event => { + form.classList.add('validated') + input.forEach(item => { + item.setCustomValidity('') + }) + axios + .post(`/api/users/${userId}`, inputValue) + // json資料 + .then(res => { + res.data.forEach(data => { + if (data.status === 'error' || !form.checkValidity()) { + return input.forEach(item => { + if (item.name === data.name) { + item.nextElementSibling.innerText = data.messages + item.setCustomValidity('error') + } + }) + } else { + return input.forEach(item => { + item.nextElementSibling.innerText = '' + }) + } + }) + }) + .then(() => { + if (form.checkValidity()) form.submit() + }) + .catch(err => { + console.log(err) + }) +}) + +form.addEventListener('submit', event => { + event.stopPropagation() + event.preventDefault() +}) diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 01f6ffdc8..9051b370e 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -1,4 +1,4 @@ -@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&family=Noto+Sans+TC:wght@400;500;700&family=Roboto&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&family=Noto+Sans+TC:wght@400;500;700&family=Roboto:wght@400;700&display=swap'); /****** Common Styles ******/ /* body */ @@ -184,6 +184,7 @@ h5 { /****** nav ******/ +/* homepage */ .navbar.navbar-vertical { padding: 0; } @@ -207,11 +208,9 @@ h5 { color: #44444f; } -.navbar-nav .nav-item:hover .nav-link { - color: #ff6600; -} - -.navbar-nav .nav-item.active .nav-link { +.nav-link.active, +.nav-item:hover .nav-link, +.nav-item.active .nav-link { color: #ff6600; } @@ -269,6 +268,26 @@ h5 { } +/* followship-navbar */ +.user-container .nav-link { + /* layout */ + border: 0; + padding: 15px; + text-align: center; + width: 130px; + + /* font */ + font-weight: 700; + font-size: 15px; + color: #657786; +} + +.user-container .nav-link.active { + color: #ff6600; + border-bottom: 2px solid #ff6600; +} + + /****** recommend-followings ******/ .recommend-followings { @@ -335,8 +354,6 @@ h5 { /****** modal ******/ .modal-dialog { padding: 0; - border: 1px solid #e6ecf0; - height: 100vh; position: absolute; top: 5%; left: 30%; @@ -403,7 +420,7 @@ h5 { border: 0px; border-radius: 0 !important; border-bottom: 1px solid #e6ecf0; - padding: 16px 24px; + padding: 16px 30px 16px 24px; } .tweet-click-block { @@ -556,19 +573,6 @@ h5 { margin-right: 16px; } -.user-container .nav-link { - border: 0; - width: 130px; - text-align: center; - font-weight: 700; - font-size: 15px; - color: #657786; -} - -.user-container .nav-link.active { - color: #ff6600; - border-bottom: 2px solid #ff6600; -} /* user-profile-modal */ .user-edit-modal .modal-body>.cover-edit, @@ -692,3 +696,256 @@ h5 { line-height: 20px; color: #696974; } + + + +/****** user edit ******/ +.user-edit-container { + margin: 24px; +} + +.user-edit-container h4 { + margin-bottom: 24px; + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 700; + font-size: 24px; + line-height: 26px; + color: #171725; +} + +.user-edit-container form { + width: 100%; + align-self: stretch; +} + +.user-edit-container .save-btn { + width: 100%; + display: flex; + justify-content: flex-end; +} + +.user-edit-container .box { + width: 100%; + background: #f5f8fa; + margin-bottom: 32px; +} + +.user-edit-container .box>input { + border-bottom: 2px solid #657786; +} + +.user-edit-container .validated .box>input:valid { + border-bottom: 2px solid #50b5ff; +} + +.user-edit-container .validated .box>input:invalid { + border-bottom: 2px solid #fc5a5a; +} + +.user-edit-container .form-label { + width: 100%; + margin: 0; + padding: 0; + font-family: 'Noto Sans TC'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 22px; + color: #696974; +} + +.user-edit-container .form-control { + background-color: transparent; + border: 0; +} + + + +/****** signin signup admin/signin ******/ +.form-row { + width: 354px; + height: 54px; + border-radius: 2px; + background-color: #f5f8fa; +} + +.account-label, +.password-label { + margin-bottom: 0; + padding: 0 0 0 10px; + font-size: 14px; +} + +.account-input, +.password-input { + padding-left: 10px; + font-size: 16px; + background-color: #f5f8fa; + border: 0; + border-bottom: 2px solid #657786; + border-radius: 0; +} + +.account-input::placeholder, +.password-input::placeholder { + color: #b5b5be; +} + +.signin-btn { + width: 354px; + height: 46px; + font-size: 20px; + border: 0; + border-radius: 50px; + background-color: #ff6600; +} + +.other-page-btn p { + width: 354px; +} + + + +/****** message ******/ +.msg-container { + /* layout */ + position: relative; + left: 50%; + transform: translate(-50%); + display: flex; + justify-content: space-between; + align-items: center; + padding: 0; + margin-bottom: 36px; + width: 394px; + height: 96px; + + /* style */ + background-color: #ffffff; + border: 0px; + border-radius: 8px; + box-shadow: 0px 4px 4px rgba(51, 51, 51, 0.04), 0px 4px 16px rgba(51, 51, 51, 0.08); +} + +.msg-container .msg { + margin-left: 24px; + font-family: 'Roboto'; + font-weight: 700; + font-size: 20px; + line-height: 28px; + color: #000000; +} + +.msg-container .btn-container { + display: flex; + align-items: center; +} + +.btn-container button { + margin-right: 24px; + background-color: transparent; + border-radius: 50%; + width: 56px; + height: 56px; +} + +.btn-container .btn-error { + border: 2px solid #fc5a5a; +} + +.btn-container .btn-success { + border: 2px solid #82c43c; +} + +.btn-container .btn-warning { + border: 2px solid #ffc542; +} + +.btn-container .btn-info { + border: 2px solid #50b5ff; +} + + + +/****** admin-users ******/ +.admin-user-page { + /* border-right: 0; */ +} + +.secondary-color { + color: #6c757d; +} + +.admin-user-info { + text-decoration: none; +} + +.admin-user-card { + width: 210px; + height: 314px; + border: 0; + border-radius: 10px; + background-color: #f6f7f8; + transition: 0.5s; +} + +.admin-user-card:hover { + transform: scale(1.03); +} + +.admin-user-card i { + font-style: normal; +} + +.admin-user-card-cover { + width: 210px; + height: 140px; +} + +.admin-user-card-cover img { + width: 210px; + height: 140px; + border-radius: 10px 10px 0 0; +} + +.admin-user-avatar { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -95%); + border: 4px solid #ffffff; + border-radius: 50%; +} + +.admin-user-avatar img { + border-radius: 50%; +} + +.admin-user-info-name { + margin-top: 35px; + font-size: 16px; +} + +.admin-user-info-account { + font-size: 14px; + color: #6c757d; +} + +.admin-user-info-count i { + vertical-align: text-top; +} + +.admin-user-info-follower i { + font-size: 14px; +} + +.admin-users-page .tweet-list { + border-bottom: 0; +} + +.admin-interact-text { + font-family: 'Montserrat'; + font-weight: 500; + font-size: 16px; +} \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index cc6863d62..ef8713ca2 100644 --- a/routes/index.js +++ b/routes/index.js @@ -7,7 +7,6 @@ const followshipController = require('../controllers/followship-controller') const profileController = require('../controllers/profile-controller') const userController = require('../controllers/user-controller') const tweetsController = require('../controllers/tweets-controller') -const adminController = require('../controllers/admin-controller') const apiProfileController = require('../controllers/api-profile-controller') const { authenticated } = require('../middleware/auth') diff --git a/routes/modules/admin.js b/routes/modules/admin.js index 2000fcfcf..d01a993ef 100644 --- a/routes/modules/admin.js +++ b/routes/modules/admin.js @@ -13,6 +13,9 @@ router.post( }), adminController.adminSignin ) + +// logout +router.get('/logout', adminController.logout) router.get('/tweets', adminAuthenticated, adminController.adminGetTweets) router.get('/users', adminAuthenticated, adminController.adminGetUsers) diff --git a/seeders/20230607144425-followships-seed-file.js b/seeders/20230607144425-followships-seed-file.js index 37ba40418..5d499af5e 100644 --- a/seeders/20230607144425-followships-seed-file.js +++ b/seeders/20230607144425-followships-seed-file.js @@ -19,23 +19,3 @@ module.exports = { await queryInterface.bulkDelete('Followships', {}) } } - -module.exports = { - up: async (queryInterface, Sequelize) => { - const users = await queryInterface.sequelize.query( - 'SELECT id FROM Users;', - { type: queryInterface.sequelize.QueryTypes.SELECT } - ) - await queryInterface.bulkInsert('Followships', - Array.from({ length: 50 }, () => ({ - follower_id: users[Math.floor(Math.random() * users.length)].id, - following_id: users[Math.floor(Math.random() * users.length)].id, - created_at: new Date(), - updated_at: new Date() - })) - ) - }, - down: async (queryInterface, Sequelize) => { - await queryInterface.bulkDelete('Followships', {}) - } -} diff --git a/seeders/20230609090000-followships-seed-file.js b/seeders/20230609090000-followships-seed-file.js deleted file mode 100644 index ca6bfd302..000000000 --- a/seeders/20230609090000-followships-seed-file.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict' - -module.exports = { - up: async (queryInterface, Sequelize) => { - const users = await queryInterface.sequelize.query( - 'SELECT id FROM Users;', - { type: queryInterface.sequelize.QueryTypes.SELECT } - ) - await queryInterface.bulkInsert('Followships', - Array.from({ length: 50 }, () => ({ - follower_id: users[Math.floor(Math.random() * users.length)].id, - following_id: users[Math.floor(Math.random() * users.length)].id, - created_at: new Date(), - updated_at: new Date() - })) - ) - }, - down: async (queryInterface, Sequelize) => { - await queryInterface.bulkDelete('Followships', {}) - } -} \ No newline at end of file diff --git a/views/admin/tweets.hbs b/views/admin/tweets.hbs index 09171b372..3f2a5c54c 100644 --- a/views/admin/tweets.hbs +++ b/views/admin/tweets.hbs @@ -1,5 +1,14 @@
    - {{!-- admin-nvabar --}} - {{> admin-navbar route='tweets'}} - {{> admin-tweets}} + {{!-- admin-navbar --}} + {{> admin-navbar route = (lookupPartial partialName)}} + + {{!--tweet-list --}} +
    +
      + + {{> (lookupPartial partialName)}} + +
    +
    +
    \ No newline at end of file diff --git a/views/admin/users.hbs b/views/admin/users.hbs deleted file mode 100644 index 1071a0958..000000000 --- a/views/admin/users.hbs +++ /dev/null @@ -1,5 +0,0 @@ -
    - {{!-- admin-nvabar --}} - {{> admin-navbar route='users'}} - {{> admin-users}} -
    \ No newline at end of file diff --git a/views/index.hbs b/views/index.hbs index 99c57a8ff..851e964ac 100644 --- a/views/index.hbs +++ b/views/index.hbs @@ -1,7 +1,6 @@ -{{!-- delete --}} -
    +
    {{!-- navbar --}} - {{> navbar}} + {{> navbar/navbar route = (lookupPartial partialName)}} {{!--tweet-list --}}
    diff --git a/views/partials/admin-navbar.hbs b/views/partials/admin-navbar.hbs index 01efc97ea..46ce36654 100644 --- a/views/partials/admin-navbar.hbs +++ b/views/partials/admin-navbar.hbs @@ -5,13 +5,13 @@
    + +{{/each}} \ No newline at end of file diff --git a/views/partials/admin-users.hbs b/views/partials/admin-users.hbs index af7beffdb..bbf782528 100644 --- a/views/partials/admin-users.hbs +++ b/views/partials/admin-users.hbs @@ -1,38 +1,35 @@ -{{!--user-list --}} - +
    + + {{/each}} + \ No newline at end of file diff --git a/views/partials/header.hbs b/views/partials/header.hbs new file mode 100644 index 000000000..3ff546b6d --- /dev/null +++ b/views/partials/header.hbs @@ -0,0 +1,25 @@ +{{#ifCond route 'homepage'}} +
  • +

    首頁

    +
  • +{{/ifCond}} + +{{#ifCond route 'users'}} +
    + + + back + + + +
    {{user.name}}
    +

    {{user.tweetsCount}} 推文

    +
    +
    +{{/ifCond}} + +{{#ifCond route 'settings'}} +
  • +

    帳戶設定

    +
  • +{{/ifCond}} \ No newline at end of file diff --git a/views/partials/message.hbs b/views/partials/message.hbs index a23e3b4c9..ecb701a1e 100644 --- a/views/partials/message.hbs +++ b/views/partials/message.hbs @@ -1,20 +1,52 @@ +{{#if success_messages}} + +{{/if}} + {{#if error_messages}} {{/if}} -{{#if success_messages}} - -

    {{tweet.description}}

    +

    {{tweet.description}}


    -
    {{replyCount}}
    +
    {{repliesCount}}
    回覆
    -
    {{likeCount}}
    +
    {{likesCount}}
    喜歡次數

    - + {{#if isLiked }}
    @@ -58,6 +53,7 @@ {{#each tweet.Replies}}
  • + {{!-- avatar --}}
    + {{!-- reply tweet --}}
    + {{!-- tweet description --}}

    {{this.comment}}

  • @@ -93,5 +92,5 @@ {{!-- modal --}} {{#with tweet}} -{{> modal-reply}} + {{> modal/modal-reply}} {{/with}} \ No newline at end of file diff --git a/views/partials/tweets-list-replies.hbs b/views/partials/tweets-list-replies.hbs new file mode 100644 index 000000000..e41fc1806 --- /dev/null +++ b/views/partials/tweets-list-replies.hbs @@ -0,0 +1,42 @@ +
    +
  • +
    + {{!-- avatar --}} +
    + +
    + +
    +
    + {{!-- user name and account --}} + + + {{!-- reply tweet --}} +
    + + +
    + + {{!-- tweet description --}} +

    {{this.comment}}

    +
    +
    +
    +
  • +
    + +{{!-- modal --}} +{{> modal/modal-reply}} \ No newline at end of file diff --git a/views/partials/tweets-list.hbs b/views/partials/tweets-list.hbs new file mode 100644 index 000000000..0b53e7d04 --- /dev/null +++ b/views/partials/tweets-list.hbs @@ -0,0 +1,58 @@ + +
  • +
    + {{!-- avatar --}} +
    + +
    + +
    + {{!-- user name and account --}} + + + {{!-- tweet description --}} +

    {{this.description}}

    + +
    + {{!-- reply icon --}} +
    + + {{this.repliesCount}} +
    + + {{!-- like icon --}} +
    + {{#if this.isLiked }} + + + + {{else}} +
    + +
    + {{/if}} + + {{this.likesCount}} +
    + +
    +
    +
    +
  • +
    + +{{!-- modal --}} +{{> modal/modal-reply}} \ No newline at end of file diff --git a/views/partials/tweets.hbs b/views/partials/tweets.hbs index bad6618b7..5cd7505cd 100644 --- a/views/partials/tweets.hbs +++ b/views/partials/tweets.hbs @@ -1,6 +1,4 @@ -
  • -

    首頁

    -
  • +{{> header route = 'homepage'}}
  • @@ -16,59 +14,10 @@
  • {{#each tweets}} - -
  • -
    -
    - -
    -
    - - -

    {{this.description}}

    - -
    -
    - - {{this.replyCount}} -
    - - {{#if this.isLiked }} -
    - -
    - {{else}} -
    - -
    - {{/if}} - {{this.likeCount}} -
    -
    -
    -
    -
    -
  • -
    - -{{!-- modal --}} -{{> modal-reply}} + {{> tweets-list}} {{/each}} {{!-- modal --}} -{{> modal-tweet}} \ No newline at end of file +{{> modal/modal-tweet}} \ No newline at end of file diff --git a/views/partials/user-edit.hbs b/views/partials/user-edit.hbs index 193950af8..d3d28cff6 100644 --- a/views/partials/user-edit.hbs +++ b/views/partials/user-edit.hbs @@ -1,35 +1,38 @@ -
    -

    帳戶設定

    -
    - {{> message}} -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - - -
    -
    - -
    -
    +
    + {{!-- header --}} + {{> header route = 'settings'}} + +
    + {{> message}} +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +
    \ No newline at end of file diff --git a/views/partials/user-followers.hbs b/views/partials/user-followers.hbs deleted file mode 100644 index dbc7a81fd..000000000 --- a/views/partials/user-followers.hbs +++ /dev/null @@ -1,72 +0,0 @@ -
    - {{!-- user header --}} -
    - - - back - - - -
    {{user.name}}
    -

    {{user.tweetsCount}} 推文

    -
    -
    - - {{!-- list nav --}} - - - {{!-- followers-list --}} - - -
    \ No newline at end of file diff --git a/views/partials/user-followings.hbs b/views/partials/user-followings.hbs deleted file mode 100644 index fb34102db..000000000 --- a/views/partials/user-followings.hbs +++ /dev/null @@ -1,49 +0,0 @@ -
    - - {{!-- user header --}} -
    - - - back - - - -
    {{user.name}}
    -

    {{user.tweetsCount}} 推文

    -
    -
    - - {{!-- list nav --}} - - - {{!-- followings-list --}} - - -
    \ No newline at end of file diff --git a/views/partials/user-followships-list.hbs b/views/partials/user-followships-list.hbs new file mode 100644 index 000000000..96644ee4d --- /dev/null +++ b/views/partials/user-followships-list.hbs @@ -0,0 +1,20 @@ +
    + + {{!-- user header --}} + {{> header route = 'users'}} + + {{!-- list nav --}} + {{> navbar/navbar-followships}} + + {{!-- followings-list --}} + {{#chooseEach followingsPage}} + {{#each user.Followings}} + {{> user-followships}} + {{/each}} + {{else}} + {{#each user.Followers}} + {{> user-followships}} + {{/each}} + {{/chooseEach}} + +
    \ No newline at end of file diff --git a/views/partials/user-followships.hbs b/views/partials/user-followships.hbs new file mode 100644 index 000000000..59ed78504 --- /dev/null +++ b/views/partials/user-followships.hbs @@ -0,0 +1,33 @@ +
  • +
    +
    + +
    + +
    +
    + + + {{#if this.isFollowing}} +
    + +
    + {{else}} +
    + + +
    + {{/if}} + +
    +

    {{this.introduction}}

    +
    +
    +
  • \ No newline at end of file diff --git a/views/partials/user-likes.hbs b/views/partials/user-likes.hbs deleted file mode 100644 index eaf9a46a6..000000000 --- a/views/partials/user-likes.hbs +++ /dev/null @@ -1,33 +0,0 @@ -
    - {{> user-profile route = 'likes'}} - - - -
    \ No newline at end of file diff --git a/views/partials/user-profile.hbs b/views/partials/user-profile.hbs index 946933b02..d4709f3d8 100644 --- a/views/partials/user-profile.hbs +++ b/views/partials/user-profile.hbs @@ -1,26 +1,22 @@ -
    - - - back - - - -
    {{user.name}}
    -

    {{user.tweetsCount}} 推文

    -
    -
    +
    + {{!-- header --}} + {{> header route = 'users'}} -
    - cover - {{#if user.isLoginUser}} + {{!-- user profile --}} +
    + cover + {{#if user.isLoginUser}}
    - avatar + avatar
    編輯個人資料
    - {{else}} + {{else}} +
    + avatar +
    mail @@ -28,33 +24,53 @@ -
    +
    - {{/if}} + {{/if}} + +
    +
    {{user.name}}
    + +

    {{user.introduction}}

    + {{user.FollowingsCount}} 個跟隨中 + {{user.FollowersCount}} 個跟隨者 +
    + + {{!-- navbar --}} + {{> navbar/navbar-profile route = (lookupPartial navbar)}} -
    -
    {{user.name}}
    - -

    {{user.introduction}}

    - {{user.FollowingsCount}} 個跟隨中 - {{user.FollowersCount}} 個跟隨者
    -
    + {{!-- modal --}} -{{> modal-edit}} +{{> modal/modal-edit}} + - + \ No newline at end of file diff --git a/views/partials/user-tweets.hbs b/views/partials/user-tweets.hbs deleted file mode 100644 index 21c0b3b54..000000000 --- a/views/partials/user-tweets.hbs +++ /dev/null @@ -1,32 +0,0 @@ -
    - {{> user-profile route = 'tweets'}} - - - -
    \ No newline at end of file diff --git a/views/users/edit.hbs b/views/test-users/edit.hbs similarity index 100% rename from views/users/edit.hbs rename to views/test-users/edit.hbs diff --git a/views/users/followers.hbs b/views/test-users/followers.hbs similarity index 100% rename from views/users/followers.hbs rename to views/test-users/followers.hbs diff --git a/views/users/followings.hbs b/views/test-users/followings.hbs similarity index 100% rename from views/users/followings.hbs rename to views/test-users/followings.hbs diff --git a/views/users/likes.hbs b/views/test-users/likes.hbs similarity index 100% rename from views/users/likes.hbs rename to views/test-users/likes.hbs diff --git a/views/users/replies.hbs b/views/test-users/replies.hbs similarity index 100% rename from views/users/replies.hbs rename to views/test-users/replies.hbs diff --git a/views/test-users/test-tweet.hbs b/views/test-users/test-tweet.hbs new file mode 100644 index 000000000..495f3469f --- /dev/null +++ b/views/test-users/test-tweet.hbs @@ -0,0 +1,151 @@ +
    + {{!-- navbar --}} + {{> navbar}} + + {{!--tweet-list --}} +
    +
      + +
    • + + 推文 +
    • +
      + + {{!-- tweet --}} +
    • +
      +
      +
      + avatar +
      +
      +
      {{tweet.User.name}}
      + +
      +
      +

      {{tweet.description}}

      + +
      + +
      +
      +
      {{repliesCount}}
      +
      回覆
      +
      {{likesCount}}
      +
      喜歡次數
      +
      + +
      +
      + + + {{#if isLiked }} +
      + +
      + {{else}} +
      + +
      + {{/if}} + +
      + +
    • + + {{#each tweet.Replies}} +
    • +
      +
      + +
      + +
      +
      +
      +
      {{this.User.name}}
      + +
      + +
      +
      回覆
      +
      @{{../tweet.User.name}}
      +
      + +

      {{this.comment}}

      +
      +
      +
      +
    • + {{/each}} + + + +
    +
    + + {{!-- recommend-followings --}} + {{> recommend-followings}} + +
    + + \ No newline at end of file diff --git a/views/test-users/test-tweets.hbs b/views/test-users/test-tweets.hbs new file mode 100644 index 000000000..4285247d9 --- /dev/null +++ b/views/test-users/test-tweets.hbs @@ -0,0 +1,167 @@ +
    + {{!-- navbar --}} + {{> navbar}} + + {{!--tweet-list --}} +
    + +
    + + {{!-- recommend-followings --}} + {{> recommend-followings}} + +
    + + + + + + \ No newline at end of file diff --git a/views/users/tweets.hbs b/views/test-users/tweets.hbs similarity index 100% rename from views/users/tweets.hbs rename to views/test-users/tweets.hbs diff --git a/views/test-users/user-likes.hbs b/views/test-users/user-likes.hbs new file mode 100644 index 000000000..f7b122660 --- /dev/null +++ b/views/test-users/user-likes.hbs @@ -0,0 +1,37 @@ + \ No newline at end of file diff --git a/views/test-users/user-profile.hbs b/views/test-users/user-profile.hbs new file mode 100644 index 000000000..f43f55dd9 --- /dev/null +++ b/views/test-users/user-profile.hbs @@ -0,0 +1,43 @@ +{{!-- {{> header route = 'users'}} --}} + +
    + cover + {{#if user.isLoginUser}} +
    + avatar +
    +
    + +
    編輯個人資料
    +
    + {{else}} +
    + + mail + + + + +
    + +
    +
    + {{/if}} + +
    +
    {{user.name}}
    + +

    {{user.introduction}}

    + {{user.FollowingsCount}} 個跟隨中 + {{user.FollowersCount}} 個跟隨者 +
    + + {{!-- navbar --}} + {{> navbar-profile route = (lookupPartial navbar)}} + +
    + +{{!-- modal --}} +{{> modal-edit}} + + diff --git a/views/partials/user-replies.hbs b/views/test-users/user-replies.hbs similarity index 99% rename from views/partials/user-replies.hbs rename to views/test-users/user-replies.hbs index 6bc60d152..006ffe439 100644 --- a/views/partials/user-replies.hbs +++ b/views/test-users/user-replies.hbs @@ -9,6 +9,7 @@
    +
    {{../user.name}} From 938544eb5d8fc11fa76013f5f1aea58861ce28c4 Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 14 Jun 2023 10:11:40 +0800 Subject: [PATCH 152/232] feat: add logout function --- controllers/user-controller.js | 55 ++++++++++++++++++---------------- routes/index.js | 2 ++ views/partials/navbar.hbs | 2 +- 3 files changed, 33 insertions(+), 26 deletions(-) diff --git a/controllers/user-controller.js b/controllers/user-controller.js index 079fb5a05..222b4c0e2 100644 --- a/controllers/user-controller.js +++ b/controllers/user-controller.js @@ -30,32 +30,37 @@ const userController = { }) .catch(err => console.log(err)) - User.findOne({ where: { email } }) - .then(user => { - if (user) { - req.flash('error_messages', 'email 已重複註冊!') - res.redirect('/signup') - throw new Error('email already exists!') - } - return bcrypt.genSalt(10) - .then(salt => bcrypt.hash(password, salt)) - .then(hash => - User.create({ - account, - name, - email, - password: hash, - role: 'user', - avatar: 'https://ionicframework.com/docs/img/demos/avatar.svg', - cover: '/images/profile/cover.png' - }) - ) - .then(() => { - req.flash('success_messages', '成功註冊帳號!') - res.redirect('/signin') + User.findOne({ where: { email } }).then(user => { + if (user) { + req.flash('error_messages', 'email 已重複註冊!') + res.redirect('/signup') + throw new Error('email already exists!') + } + return bcrypt + .genSalt(10) + .then(salt => bcrypt.hash(password, salt)) + .then(hash => + User.create({ + account, + name, + email, + password: hash, + role: 'user', + avatar: 'https://ionicframework.com/docs/img/demos/avatar.svg', + cover: '/images/profile/cover.png' }) - .catch(err => console.log(err)) - }) + ) + .then(() => { + req.flash('success_messages', '成功註冊帳號!') + res.redirect('/signin') + }) + .catch(err => console.log(err)) + }) + }, + logout: (req, res) => { + req.flash('success_messages', '登出成功!') + req.logout() + res.redirect('/signin') }, postLike: async (req, res, next) => { const { tweetId } = req.params diff --git a/routes/index.js b/routes/index.js index 695281e0f..a6f220b94 100644 --- a/routes/index.js +++ b/routes/index.js @@ -30,6 +30,8 @@ router.post( // signup router.get('/signup', userController.signupPage) router.post('/signup', userController.signup) +// logout +router.get('/logout', userController.logout) // index router.get('/tweets/:tweetId/replies', authenticated, tweetsController.getTweet) diff --git a/views/partials/navbar.hbs b/views/partials/navbar.hbs index e1169ddad..207abab5c 100644 --- a/views/partials/navbar.hbs +++ b/views/partials/navbar.hbs @@ -30,7 +30,7 @@
    +{{/if}} +{{#if errors}} + {{#each errors}} + + {{/each}} {{/if}} \ No newline at end of file diff --git a/views/signup.hbs b/views/signup.hbs index 123af86e3..bcfa8f278 100644 --- a/views/signup.hbs +++ b/views/signup.hbs @@ -8,16 +8,16 @@ {{> message}} {{/if}} From 56007793c853c514d550e76b52b0264a0600e3cd Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 14 Jun 2023 13:20:44 +0800 Subject: [PATCH 159/232] =?UTF-8?q?feat:=20add=20=E5=9B=9E=E8=A6=86?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=8E=92=E5=BA=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/profile-controller.js | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index f0994c92a..92412215b 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -130,6 +130,7 @@ const profileController = { attributes: ['id'] } ], + order: [['createdAt', 'DESC']], limit, offset }) From 07816432ef50e1518e810cedc00ba54eb6ddc85a Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 14 Jun 2023 13:31:27 +0800 Subject: [PATCH 160/232] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=E5=96=9C?= =?UTF-8?q?=E6=AD=A1=E7=9A=84=E5=85=A7=E5=AE=B9=E6=99=82=E9=96=93=E9=A1=AF?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/profile-controller.js | 2 ++ views/partials/user-likes.hbs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index 92412215b..74427bbd9 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -172,6 +172,7 @@ const profileController = { // 整理資料 const tweetsData = likes.rows.map((like, index) => ({ ...like.Tweet.toJSON(), + createdAt: like.createdAt, likesCount: counts[index].likesCount, repliesCount: counts[index].repliesCount, isLiked: loginUser.Likes.some(l => l.TweetId === like.TweetId) @@ -179,6 +180,7 @@ const profileController = { // pagination const pagination = getPagination(page, limit, likes.count) const partialName = 'user-likes' + console.log(tweetsData[0]) // render res.render('index', { user: userData, tweets: tweetsData, pagination, route, partialName, nav, followingData }) } catch (err) { diff --git a/views/partials/user-likes.hbs b/views/partials/user-likes.hbs index 011140fe2..cd8d3e42b 100644 --- a/views/partials/user-likes.hbs +++ b/views/partials/user-likes.hbs @@ -13,7 +13,7 @@
    {{this.User.name}} - +

    {{this.description}}

    From f80bdbc9cd32f61e7292d5209b5edf7b403a3f70 Mon Sep 17 00:00:00 2001 From: shaochenn Date: Wed, 14 Jun 2023 13:31:54 +0800 Subject: [PATCH 161/232] merge origin/master & feature/layout --- views/test-users/edit.hbs | 92 ---------------- views/test-users/followers.hbs | 87 ---------------- views/test-users/followings.hbs | 81 --------------- views/test-users/likes.hbs | 52 ---------- views/test-users/replies.hbs | 46 -------- views/test-users/test-tweet.hbs | 151 --------------------------- views/test-users/test-tweets.hbs | 167 ------------------------------ views/test-users/tweets.hbs | 52 ---------- views/test-users/user-likes.hbs | 37 ------- views/test-users/user-profile.hbs | 43 -------- views/test-users/user-replies.hbs | 28 ----- 11 files changed, 836 deletions(-) delete mode 100644 views/test-users/edit.hbs delete mode 100644 views/test-users/followers.hbs delete mode 100644 views/test-users/followings.hbs delete mode 100644 views/test-users/likes.hbs delete mode 100644 views/test-users/replies.hbs delete mode 100644 views/test-users/test-tweet.hbs delete mode 100644 views/test-users/test-tweets.hbs delete mode 100644 views/test-users/tweets.hbs delete mode 100644 views/test-users/user-likes.hbs delete mode 100644 views/test-users/user-profile.hbs delete mode 100644 views/test-users/user-replies.hbs diff --git a/views/test-users/edit.hbs b/views/test-users/edit.hbs deleted file mode 100644 index dd5f49f35..000000000 --- a/views/test-users/edit.hbs +++ /dev/null @@ -1,92 +0,0 @@ -
    - {{> navbar route = 'setting'}} - -
    -
      - -
      -

      帳戶設定

      -
      -
      -
      - - -
      請輸入帳號!
      -
      -
      - - -
      請輸入名稱!
      -
      -
      - - -
      請輸入Email!
      -
      -
      - - -
      請輸入密碼!
      -
      -
      - - -
      請輸入密碼!
      -
      -
      - -
      -
      -
      - -
    -
    - -
    - - diff --git a/views/test-users/followers.hbs b/views/test-users/followers.hbs deleted file mode 100644 index f9df2370c..000000000 --- a/views/test-users/followers.hbs +++ /dev/null @@ -1,87 +0,0 @@ -
    - {{! navbar }} - {{> navbar}} - - {{!tweet-list }} -
    -
      -
      - {{!-- user header --}} -
      - - - back - - - -
      {{user.name}}
      -

      {{user.tweetsCount}} 推文

      -
      -
      - - {{!-- list nav --}} - - - {{!-- followers-list --}} -
      -
      - - {{/each}} -
    - {{#if pagination.hasManyPages}} - {{> pagination route = route }} - {{/if}} -
    - -
    - - {{! recommend-followings }} - {{> recommend-followings}} -
    \ No newline at end of file diff --git a/views/test-users/followings.hbs b/views/test-users/followings.hbs deleted file mode 100644 index 80ad59b81..000000000 --- a/views/test-users/followings.hbs +++ /dev/null @@ -1,81 +0,0 @@ -
    - {{! navbar }} - {{> navbar}} - - {{!tweet-list }} -
    -
      -
      - - {{!-- user header --}} -
      - - - back - - - -
      {{user.name}}
      -

      {{user.tweetsCount}} 推文

      -
      -
      - - {{!-- list nav --}} - - - {{!-- followings-list --}} -
      -
      - - {{/each}} -
    - {{#if pagination.hasManyPages}} - {{> pagination route = route }} - {{/if}} -
    - -
    - {{! recommend-followings }} - {{> recommend-followings}} -
    \ No newline at end of file diff --git a/views/test-users/likes.hbs b/views/test-users/likes.hbs deleted file mode 100644 index 6633be368..000000000 --- a/views/test-users/likes.hbs +++ /dev/null @@ -1,52 +0,0 @@ -
    - {{! navbar }} - {{> navbar route = 'profile'}} - - {{!tweet-list }} -
    - -
    - - {{! recommend-followings }} - {{> recommend-followings}} - -
    \ No newline at end of file diff --git a/views/test-users/replies.hbs b/views/test-users/replies.hbs deleted file mode 100644 index e3e574a63..000000000 --- a/views/test-users/replies.hbs +++ /dev/null @@ -1,46 +0,0 @@ -
    - {{! navbar }} - {{> navbar route = 'profile'}} - - {{!tweet-list }} -
    - -
    - - {{! recommend-followings }} - {{> recommend-followings}} - -
    \ No newline at end of file diff --git a/views/test-users/test-tweet.hbs b/views/test-users/test-tweet.hbs deleted file mode 100644 index 495f3469f..000000000 --- a/views/test-users/test-tweet.hbs +++ /dev/null @@ -1,151 +0,0 @@ -
    - {{!-- navbar --}} - {{> navbar}} - - {{!--tweet-list --}} -
    -
      - -
    • - - 推文 -
    • -
      - - {{!-- tweet --}} -
    • -
      -
      -
      - avatar -
      -
      -
      {{tweet.User.name}}
      - -
      -
      -

      {{tweet.description}}

      - -
      - -
      -
      -
      {{repliesCount}}
      -
      回覆
      -
      {{likesCount}}
      -
      喜歡次數
      -
      - -
      -
      - - - {{#if isLiked }} -
      - -
      - {{else}} -
      - -
      - {{/if}} - -
      - -
    • - - {{#each tweet.Replies}} -
    • -
      -
      - -
      - -
      -
      -
      -
      {{this.User.name}}
      - -
      - -
      -
      回覆
      -
      @{{../tweet.User.name}}
      -
      - -

      {{this.comment}}

      -
      -
      -
      -
    • - {{/each}} - - - -
    -
    - - {{!-- recommend-followings --}} - {{> recommend-followings}} - -
    - - \ No newline at end of file diff --git a/views/test-users/test-tweets.hbs b/views/test-users/test-tweets.hbs deleted file mode 100644 index 4285247d9..000000000 --- a/views/test-users/test-tweets.hbs +++ /dev/null @@ -1,167 +0,0 @@ -
    - {{!-- navbar --}} - {{> navbar}} - - {{!--tweet-list --}} -
    - -
    - - {{!-- recommend-followings --}} - {{> recommend-followings}} - -
    - - - - - - \ No newline at end of file diff --git a/views/test-users/tweets.hbs b/views/test-users/tweets.hbs deleted file mode 100644 index bbc94ce70..000000000 --- a/views/test-users/tweets.hbs +++ /dev/null @@ -1,52 +0,0 @@ -
    - {{! navbar }} - {{> navbar route = 'profile'}} - - {{!tweet-list }} -
    - -
    - - {{! recommend-followings }} - {{> recommend-followings}} - -
    \ No newline at end of file diff --git a/views/test-users/user-likes.hbs b/views/test-users/user-likes.hbs deleted file mode 100644 index f7b122660..000000000 --- a/views/test-users/user-likes.hbs +++ /dev/null @@ -1,37 +0,0 @@ - \ No newline at end of file diff --git a/views/test-users/user-profile.hbs b/views/test-users/user-profile.hbs deleted file mode 100644 index f43f55dd9..000000000 --- a/views/test-users/user-profile.hbs +++ /dev/null @@ -1,43 +0,0 @@ -{{!-- {{> header route = 'users'}} --}} - -
    - cover - {{#if user.isLoginUser}} -
    - avatar -
    -
    - -
    編輯個人資料
    -
    - {{else}} -
    - - mail - - - - -
    - -
    -
    - {{/if}} - -
    -
    {{user.name}}
    - -

    {{user.introduction}}

    - {{user.FollowingsCount}} 個跟隨中 - {{user.FollowersCount}} 個跟隨者 -
    - - {{!-- navbar --}} - {{> navbar-profile route = (lookupPartial navbar)}} - -
    - -{{!-- modal --}} -{{> modal-edit}} - - diff --git a/views/test-users/user-replies.hbs b/views/test-users/user-replies.hbs deleted file mode 100644 index 006ffe439..000000000 --- a/views/test-users/user-replies.hbs +++ /dev/null @@ -1,28 +0,0 @@ -
    - {{> user-profile route = 'replies'}} - - -
      - {{#each replies}} -
    • -
      -
      - -
      - -
      - {{../user.name}} - - -
      - 回覆 - -
      -

      {{this.comment}}

      -
      -
      -
      -
    • - {{/each}} -
    -
    \ No newline at end of file From c0528a632c8281ae9789ef1a61830ef9d0959278 Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 14 Jun 2023 13:36:17 +0800 Subject: [PATCH 162/232] =?UTF-8?q?feat:=20=E5=B0=87=E8=BF=BD=E8=B9=A4?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E8=AE=8A=E7=82=BA=E6=AF=8F=E6=AC=A1=E9=83=BD?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/followship-controller.js | 2 +- controllers/profile-controller.js | 13 ++++++++----- controllers/tweets-controller.js | 4 ++-- routes/index.js | 20 +++++++++++++------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/controllers/followship-controller.js b/controllers/followship-controller.js index ad53ab534..06bcbb57b 100644 --- a/controllers/followship-controller.js +++ b/controllers/followship-controller.js @@ -64,7 +64,7 @@ const followshipController = { isFollowed: req.user.Followings.some(f => f.id === user.id) })) .sort((a, b) => b.followerCount - a.followerCount) - req.session.followingData = result.slice(0, topFollowedUsersNumber - 1) + req.followingData = result.slice(0, topFollowedUsersNumber - 1) return next() }) .catch(err => next(err)) diff --git a/controllers/profile-controller.js b/controllers/profile-controller.js index 74427bbd9..3fc53fd21 100644 --- a/controllers/profile-controller.js +++ b/controllers/profile-controller.js @@ -55,7 +55,8 @@ const profileController = { } }, getUserTweets: async (req, res, next) => { - const { userData, followingData } = req.session + const { userData } = req.session + const { followingData } = req // 取得 id const { userId } = req.params const loginUser = helpers.getUser(req) @@ -107,7 +108,8 @@ const profileController = { } }, getUserReplies: async (req, res, next) => { - const { userData, followingData } = req.session + const { userData } = req.session + const { followingData } = req // 取得userId const { userId } = req.params const route = `users/${userId}/replies` @@ -146,7 +148,8 @@ const profileController = { } }, getUserLikes: async (req, res, next) => { - const { userData, followingData } = req.session + const { userData } = req.session + const { followingData } = req const loginUser = helpers.getUser(req) const { userId } = req.params const route = `users/${userId}/likes` @@ -190,7 +193,7 @@ const profileController = { getUserFollowings: async (req, res, next) => { const loginUser = helpers.getUser(req) const { userId } = req.params - const { followingData } = req.session + const { followingData } = req // 判斷active const followings = true const route = `users/${userId}/followings` @@ -252,7 +255,7 @@ const profileController = { getUserFollowers: async (req, res, next) => { const loginUser = helpers.getUser(req) const { userId } = req.params - const { followingData } = req.session + const { followingData } = req // 判斷active const followers = true const route = `users/${userId}/followers` diff --git a/controllers/tweets-controller.js b/controllers/tweets-controller.js index ff2e4c828..b7c61f525 100644 --- a/controllers/tweets-controller.js +++ b/controllers/tweets-controller.js @@ -6,7 +6,7 @@ const tweetsController = { getTweets: async (req, res, next) => { // 取得登入使用者的資料 const loginUser = helpers.getUser(req) - const { followingData } = req.session + const { followingData } = req try { let tweets = await Tweet.findAll({ include: [User, { model: Like }, { model: Reply, include: User }], @@ -33,7 +33,7 @@ const tweetsController = { getTweet: async (req, res, next) => { const { tweetId } = req.params const user = helpers.getUser(req) - const { followingData } = req.session + const { followingData } = req try { const tweet = await Tweet.findByPk(tweetId, { include: [User, { model: Like }, { model: Reply, include: User }] diff --git a/routes/index.js b/routes/index.js index a6f220b94..85c377f3e 100644 --- a/routes/index.js +++ b/routes/index.js @@ -39,15 +39,21 @@ router.post('/tweets/:tweetId/replies', authenticated, tweetsController.postRepl router.post('/tweets/:tweetId/like', authenticated, userController.postLike) router.post('/tweets/:tweetId/unlike', authenticated, userController.postUnlike) router.get('/tweets', authenticated, followshipController.getTopFollowedUsers, tweetsController.getTweets) -router.post('/tweets', authenticated, tweetsController.postTweet) +router.post('/tweets', authenticated, followshipController.getTopFollowedUsers, tweetsController.postTweet) // profile -router.get('/users/:userId/tweets', authenticated, profileController.getUser, profileController.getUserTweets) -router.get('/users/:userId/replies', authenticated, profileController.getUserReplies) -router.get('/users/:userId/likes', authenticated, profileController.getUserLikes) -router.get('/users/:userId/followings', authenticated, profileController.getUserFollowings) -router.get('/users/:userId/followers', authenticated, profileController.getUserFollowers) -router.get('/users/:userId', authenticated, profileController.editUserAccount) +router.get( + '/users/:userId/tweets', + authenticated, + followshipController.getTopFollowedUsers, + profileController.getUser, + profileController.getUserTweets +) +router.get('/users/:userId/replies', authenticated, followshipController.getTopFollowedUsers, profileController.getUserReplies) +router.get('/users/:userId/likes', authenticated, followshipController.getTopFollowedUsers, profileController.getUserLikes) +router.get('/users/:userId/followings', authenticated, followshipController.getTopFollowedUsers, profileController.getUserFollowings) +router.get('/users/:userId/followers', authenticated, followshipController.getTopFollowedUsers, profileController.getUserFollowers) +router.get('/users/:userId', authenticated, followshipController.getTopFollowedUsers, profileController.editUserAccount) router.put( '/users/:userId', authenticated, From a6e3b5bd272625c9d74f205e14b22cdf180c7a12 Mon Sep 17 00:00:00 2001 From: shaochenn <91368309+shaochenn@users.noreply.github.com> Date: Wed, 14 Jun 2023 13:43:25 +0800 Subject: [PATCH 163/232] Delete partial-helpers.js --- helpers/partial-helpers.js | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 helpers/partial-helpers.js diff --git a/helpers/partial-helpers.js b/helpers/partial-helpers.js deleted file mode 100644 index 7daa83068..000000000 --- a/helpers/partial-helpers.js +++ /dev/null @@ -1,7 +0,0 @@ -const Handlebars = require('handlebars') - -Handlebars.registerHelper('lookupPartial', function (partialName) { - return partialName -}) - -module.exports = Handlebars From 0ddba945f7a7403019c37b078e389e4e75e7be09 Mon Sep 17 00:00:00 2001 From: alvin Date: Wed, 14 Jun 2023 16:20:15 +0800 Subject: [PATCH 164/232] =?UTF-8?q?fix=20:=20=E4=BF=AE=E6=AD=A3edit?= =?UTF-8?q?=E9=A0=81=E9=9D=A2=E9=8C=AF=E8=AA=A4=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 11 +-- controllers/tweets-controller.js | 1 + public/javascript/edit.js | 12 ++-- public/stylesheets/style.css | 102 +++++++++------------------ views/partials/modal/modal-tweet.hbs | 45 +++++++----- views/partials/user-edit.hbs | 11 ++- 6 files changed, 78 insertions(+), 104 deletions(-) diff --git a/app.js b/app.js index 6cde9756d..30c657fdc 100644 --- a/app.js +++ b/app.js @@ -12,13 +12,8 @@ const passport = require('./config/passport') // helpers const handlebarsHelpers = require('./helpers/handlebars-helpers') -const partialHelpers = require('./helpers/partial-helpers') -const authHelpers = require('./_helpers') -const helpers = { - ...handlebarsHelpers, - ...partialHelpers, - ...authHelpers -} +const helpers = require('./_helpers') + const previousPage = require('./middleware/previous-page') // files @@ -28,7 +23,7 @@ app.use(express.static('public')) const port = process.env.PORT || 3000 const SESSION_SECRET = process.env.SESSION_SECRET || 'simple_twitter_session_secret' -app.engine('hbs', handlebars({ extname: '.hbs', defaultLayout: 'main', helpers: helpers })) +app.engine('hbs', handlebars({ extname: '.hbs', defaultLayout: 'main', helpers: handlebarsHelpers })) app.set('view engine', 'hbs') app.use(express.urlencoded({ extended: true })) diff --git a/controllers/tweets-controller.js b/controllers/tweets-controller.js index db7ac4548..e22724d18 100644 --- a/controllers/tweets-controller.js +++ b/controllers/tweets-controller.js @@ -62,6 +62,7 @@ const tweetsController = { let { description } = req.body const UserId = helpers.getUser(req).id try { + console.log('aaaaaaaaaa') // 推文字數不可超過140字 if (description.length > 140) throw new Error('字數不可超過140字') diff --git a/public/javascript/edit.js b/public/javascript/edit.js index f72f53659..e9e6c5f6f 100644 --- a/public/javascript/edit.js +++ b/public/javascript/edit.js @@ -1,4 +1,4 @@ -const form = document.querySelector('form') +const form = document.querySelector('#edit-form') const input = document.querySelectorAll('input') const button = document.querySelector('.save-btn') @@ -12,16 +12,14 @@ const matches = url.match(/\/(\d+)/) const userId = matches[1] const inputValue = {} -form.addEventListener('input', () => { - input.forEach(item => { - inputValue[item.name] = item.value - }) -}) button.addEventListener('click', event => { form.classList.add('validated') input.forEach(item => { - item.setCustomValidity('') + inputValue[item.name] = item.value + if (item.value) { + return item.setCustomValidity('') + } }) axios .post(`/api/users/${userId}`, inputValue) diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index e1fb93fd2..2b1d8a269 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -22,7 +22,6 @@ hr { margin: 16px 0; } - /* font */ h4 { font-weight: 700; @@ -95,7 +94,6 @@ h5 { color: #6c757d; } - /* btn */ .btn { /* layout */ @@ -168,8 +166,6 @@ h5 { color: #ffffff; } - - /****** index ******/ .home-page { /* layout */ @@ -181,8 +177,6 @@ h5 { overflow-y: auto; } - - /****** nav ******/ /* homepage */ .navbar.navbar-vertical { @@ -267,7 +261,6 @@ h5 { background-image: url('/images/navbar/logout_colored.svg'); } - /* followship-navbar */ .user-container .nav-link { /* layout */ @@ -287,8 +280,6 @@ h5 { border-bottom: 2px solid #ff6600; } - - /****** recommend-followings ******/ .recommend-followings { /* layout */ @@ -349,8 +340,6 @@ h5 { width: 76px; } - - /****** modal ******/ .modal-dialog { padding: 0; @@ -371,7 +360,7 @@ h5 { height: 57px; margin: 0; padding: 8px 16px; - border-bottom: 1px solid #E6ECF0; + border-bottom: 1px solid #e6ecf0; } .modal-close-btn { @@ -405,8 +394,6 @@ h5 { height: 100%; } - - /****** tweets-list ******/ .home-list { /* layout */ @@ -487,8 +474,6 @@ h5 { margin-right: 128px; } - - /****** profile ******/ .profile-header { padding: 16px 24px; @@ -549,8 +534,8 @@ h5 { color: #6c757d; } -.user-container>.card>div>span, -.user-container>.card>div>span>a { +.user-container > .card > div > span, +.user-container > .card > div > span > a { font-family: 'Noto Sans TC'; font-style: normal; font-weight: 400; @@ -567,20 +552,19 @@ h5 { margin: 16px; } -.profile-btn-block >.mail-btn, -.profile-btn-block >.notification-btn { +.profile-btn-block > .mail-btn, +.profile-btn-block > .notification-btn { width: 40px; margin-right: 16px; } - /* user-profile-modal */ -.user-edit-modal .modal-body>.cover-edit, -.user-edit-modal .modal-body>.avatar-edit { +.user-edit-modal .modal-body > .cover-edit, +.user-edit-modal .modal-body > .avatar-edit { position: relative; } -.user-edit-modal .modal-body>.cover-edit>.cover-img { +.user-edit-modal .modal-body > .cover-edit > .cover-img { -webkit-filter: brightness(0.5); filter: brightness(0.5); width: 100%; @@ -588,7 +572,7 @@ h5 { border-radius: 0px; } -.user-edit-modal .modal-body>.cover-edit>.cover { +.user-edit-modal .modal-body > .cover-edit > .cover { position: absolute; top: 0; left: 0; @@ -599,15 +583,15 @@ h5 { height: 100%; } -.user-edit-modal .modal-body>.cover-edit>.cover>.form-control, -.user-edit-modal .modal-body>.avatar-edit>.avatar>.form-control { +.user-edit-modal .modal-body > .cover-edit > .cover > .form-control, +.user-edit-modal .modal-body > .avatar-edit > .avatar > .form-control { top: 0; width: 0; opacity: 0; pointer-events: none; } -.user-edit-modal .modal-body>.cover-edit>.cover>.form-label { +.user-edit-modal .modal-body > .cover-edit > .cover > .form-label { margin: 0; top: 0; left: 0; @@ -615,7 +599,7 @@ h5 { cursor: pointer; } -.user-edit-modal .modal-body>.cover-edit>.cover>.cover-delete { +.user-edit-modal .modal-body > .cover-edit > .cover > .cover-delete { width: 15px; text-align: center; border: 0; @@ -630,7 +614,7 @@ h5 { z-index: 0; } -.user-edit-modal .modal-body>.avatar-edit>.avatar { +.user-edit-modal .modal-body > .avatar-edit > .avatar { position: absolute; top: 0; left: 75px; @@ -640,37 +624,37 @@ h5 { height: 100%; } -.user-edit-modal .modal-body>.avatar-edit>.avatar>.form-label { +.user-edit-modal .modal-body > .avatar-edit > .avatar > .form-label { margin: 0; top: 0; color: #ffffff; cursor: pointer; } -.user-edit-modal .modal-body>.form-text { +.user-edit-modal .modal-body > .form-text { margin: 80px 16px 0; } -.user-edit-modal .modal-body>.form-text .box { +.user-edit-modal .modal-body > .form-text .box { background: #f5f8fa; } -.user-edit-modal .modal-body>.form-text .box>input, -.user-edit-modal .modal-body>.form-text .box>textarea { +.user-edit-modal .modal-body > .form-text .box > input, +.user-edit-modal .modal-body > .form-text .box > textarea { border-bottom: 2px solid #657786; } -.user-edit-modal .modal-body>.form-text .box>input:valid, -.user-edit-modal .modal-body>.form-text .box>textarea:valid { +.user-edit-modal .modal-body > .form-text .box > input:valid, +.user-edit-modal .modal-body > .form-text .box > textarea:valid { border-bottom: 2px solid #50b5ff; } -.user-edit-modal .modal-body>.form-text .box>input:invalid, -.user-edit-modal .modal-body>.form-text .box>textarea:invalid { +.user-edit-modal .modal-body > .form-text .box > input:invalid, +.user-edit-modal .modal-body > .form-text .box > textarea:invalid { border-bottom: 2px solid #fc5a5a; } -.user-edit-modal .modal-body>.form-text .form-label { +.user-edit-modal .modal-body > .form-text .form-label { margin: 0; padding: 0; font-family: 'Noto Sans TC'; @@ -681,13 +665,13 @@ h5 { color: #696974; } -.user-edit-modal .modal-body>.form-text .form-control { +.user-edit-modal .modal-body > .form-text .form-control { background-color: transparent; border: 0; } -.user-edit-modal .modal-body>.form-text .name-amount, -.user-edit-modal .modal-body>.form-text .introduction-amount { +.user-edit-modal .modal-body > .form-text .name-amount, +.user-edit-modal .modal-body > .form-text .introduction-amount { text-align: right; font-family: 'Noto Sans TC'; font-style: normal; @@ -697,8 +681,6 @@ h5 { color: #696974; } - - /****** user edit ******/ .user-edit-container { margin: 24px; @@ -731,15 +713,15 @@ h5 { margin-bottom: 32px; } -.user-edit-container .box>input { +.user-edit-container .box > input { border-bottom: 2px solid #657786; } -.user-edit-container .validated .box>input:valid { +.user-edit-container .validated .box > input:valid { border-bottom: 2px solid #50b5ff; } -.user-edit-container .validated .box>input:invalid { +.user-edit-container .validated .box > input:invalid { border-bottom: 2px solid #fc5a5a; } @@ -760,8 +742,6 @@ h5 { border: 0; } - - /****** signin signup admin/signin ******/ .form-row { width: 354px; @@ -805,8 +785,6 @@ h5 { width: 354px; } - - /****** message ******/ .msg-container { /* layout */ @@ -866,8 +844,6 @@ h5 { border: 2px solid #50b5ff; } - - /****** admin-users ******/ .admin-user-page { /* border-right: 0; */ @@ -948,11 +924,11 @@ h5 { font-family: 'Montserrat'; font-weight: 500; font-size: 16px; -<<<<<<< HEAD - color: #6c757d; } -.tweet-text { +/* -------------------------------------- */ + +/* .tweet-text { margin-left: 8px; margin-right: 3px; width: auto; @@ -1021,11 +997,8 @@ h5 { .hr { border: 0px; - /* 不要框架 */ height: 1px; - /* 設定 1px 的高度 */ background: #e6ecf0; - /* 讓背景色填滿高度 1px 的元素空間 */ margin: 20px 0; } @@ -1063,7 +1036,6 @@ h5 { margin: 10px auto 0; } -/* 錯誤訊息 */ .invalid-feedback .tweet-feedback, .invalid-feedback .reply-feedback { display: none; @@ -1076,10 +1048,8 @@ h5 { form.was-validated .invalid-message:invalid ~ .invalid-parent .tweet-feedback, form.was-validated .invalid-message:invalid ~ .invalid-parent .reply-feedback { display: initial; - /* 顯示 */ } -/* message */ .msg-container { position: relative; left: 50%; @@ -1118,8 +1088,7 @@ form.was-validated .invalid-message:invalid ~ .invalid-parent .reply-feedback { width: 56px; height: 56px; } - -/* input */ +*/ form.invalid-feedback { display: none; font-size: 0.8em; @@ -1132,6 +1101,3 @@ form.invalid-feedback { .validated .form-control:invalid ~ .invalid-feedback { display: initial; } -======= -} ->>>>>>> origin diff --git a/views/partials/modal/modal-tweet.hbs b/views/partials/modal/modal-tweet.hbs index c6d675a11..a36c92a5a 100644 --- a/views/partials/modal/modal-tweet.hbs +++ b/views/partials/modal/modal-tweet.hbs @@ -1,27 +1,34 @@ -{{!-- tweet modal --}} -