diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000000..0486d8c813
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,2 @@
+IMGUR_CLIENT_ID=
+JWT_SECRET=
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000000..ceaa7dc6e6
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,2 @@
+/node_modules/*
+/tests/*
\ No newline at end of file
diff --git a/.eslintrc.yml b/.eslintrc.yml
new file mode 100644
index 0000000000..495c19c369
--- /dev/null
+++ b/.eslintrc.yml
@@ -0,0 +1,12 @@
+env:
+ browser: true
+ commonjs: true
+ es2021: true
+extends:
+ - standard
+parserOptions:
+ ecmaVersion: 12
+rules:
+ arrow-parens:
+ - warn
+ - as-needed
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..4a13145442
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,53 @@
+* text=auto
+
+# Source code
+*.css text diff=css
+*.html text diff=html
+*.js text
+*.json text
+
+# Documentation
+*.markdown text diff=markdown
+*.md text diff=markdown
+*.txt text
+
+# Templates
+*.handlebars text
+*.hbs text
+
+# Configs
+*.cnf text
+*.conf text
+*.config text
+.editorconfig text
+.env text
+.env.* text
+.gitattributes text
+.gitconfig text
+*.lock text -diff
+package.json text eol=lf
+package-lock.json text -diff
+yarn.lock text -diff
+*.yaml text
+*.yml text
+browserslist text
+
+# Heroku
+Procfile text
+
+# Graphics
+*.gif binary
+*.ico binary
+*.jpg binary
+*.jpeg binary
+*.pdf binary
+*.png binary
+# SVG treated as an asset (binary) by default.
+*.svg text
+# If you want to treat it as binary,
+# use the following line instead.
+# *.svg binary
+*.webp binary
+
+# Ignore files (like .npmignore or .gitignore)
+*.*ignore text
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 4daff23660..cc2a8eea29 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
.DS_Store
*.DS_Store
+frontend-test.html
# Logs
logs
@@ -42,6 +43,7 @@ build/Release
# Dependency directories
node_modules/
jspm_packages/
+temp/*
# TypeScript v1 declaration files
typings/
diff --git a/.travis.yml b/.travis.yml
index 1ada9d4d94..0d0f17f1aa 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,7 +7,7 @@ services:
# 設定參數(Travis CI 會按照參數分別執行)
env:
- - NODE_ENV=travis
+ - NODE_ENV=travis JWT_SECRET=alphacamp
# 在 install 前執行的指令
before_install:
diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000000..6feca7ecec
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: NODE_ENV=production node app.js
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..c8191e449f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,112 @@
+# Simple Twitter
+
+
+
+## About - 介紹
+這是一個前後端分離的小組專案,前端使用React,後端則使用Node.js、Express搭配MySQL關連式資料庫所打造的API Server。
+Simple Twitter 提供後台管理及前台頁面,使用者可以註冊,登入,推文,回覆推文,喜歡跟追蹤使用者等功能。
+
+## Website - https://zebrrrra.github.io/AC_twitter_frontend
+## 前端github repo - https://github.com/zebrrrra/AC_twitter_frontend
+
+
+## API - 接口文件
+文件內提供每個街口的的使用方式,回傳,成功跟失敗的回傳資訊:
+https://www.notion.so/API-c1a90264a00848d2af202689ae0148be
+
+
+## Environment - 開發環境
+* node v14.16.0
+* nodemon
+
+## Installation and Execution - 安裝與執行步驟
+### 1. 開啟Terminal, Clone此專案至本機:
+```
+git clone https://github.com/klu0926/twitter-api-2023.git
+```
+### 2. 進入存放此專案的資料夾
+```
+cd twitter-api-2023
+```
+### 3. 安裝所需要的NPM Packages
+```
+npm install
+```
+
+### 4. 在SQL WorkBench 建立資料庫 (在workBench內輸入)
+```
+create database ac_twitter_workspace
+```
+### 5. 建立資料庫 tables
+```
+npx sequelize db:migrate
+```
+
+### 5. 建立資料庫 seed
+```
+npx sequelize db:seed:all
+```
+
+### 6. 建立.env 檔案放入密碼 (參考.env.example)
+```
+IMGUR_CLIENT_ID= 你的密碼
+JWT_SECRET= 你的密碼
+```
+### 7. 啟動伺服器 (使用 nodemon)
+```
+npm run dev
+```
+
+### 8. Terminal出現以下字樣代表成功啟動!
+```
+Example app listening on port 3000!
+```
+
+
+## Seed Accounts - 測試帳號
+專案提供 1 個後台管理者帳號與跟 9 位使用者帳號
+管理者帳號只可以使用後台功能,使用者帳號只能使用前台功能
+### # 管理者帳號 - 後台
+account: root
+email: root@example.com
+password: 12345678
+### # 使用者帳號 - 前台
+account: user1 ~ user9
+email: user1@example.com
+password: 12345678
+
+## Development Tools - 開發工具
+* bcrypt-nodejs: "0.0.3",
+* bcryptjs: "^2.4.3",
+* body-parser: "^1.18.3",
+* chai: "^4.2.0",
+* connect-flash: "^0.1.1",
+* cors: "^2.8.5",
+* dotenv: "^10.0.0",
+* express: "^4.16.4",
+* express-session: "^1.15.6",
+* faker: "^4.1.0",
+* imgur: "^1.0.2",
+* jsonwebtoken: "^8.5.1",
+* method-override: "^3.0.0",
+* mocha: "^6.0.2",
+* multer: "^1.4.3",
+* mysql2: "^1.6.4",
+* passport: "^0.4.0",
+* passport-jwt: "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"
+
+
+## Team - 團隊成員
+### 前端
+[zebrrrra](https://github.com/zebrrrra)
+[Jena Lin](https://github.com/J6127)
+### 後端
+[kim1037](https://github.com/kim1037)
+[klu0926](https://github.com/klu0926)
+
+
diff --git a/_helpers.js b/_helpers.js
index b7a88770e8..d83196d1fb 100644
--- a/_helpers.js
+++ b/_helpers.js
@@ -1,8 +1,7 @@
-
-function getUser(req) {
- return req.user;
+function getUser (req) {
+ return req.user
}
module.exports = {
- getUser,
-};
\ No newline at end of file
+ getUser
+}
diff --git a/app.js b/app.js
index 842c6bd679..9af33ca3fb 100644
--- a/app.js
+++ b/app.js
@@ -1,15 +1,50 @@
-const express = require('express')
-const helpers = require('./_helpers');
+if (process.env.NODE_ENV !== 'production') {
+ require('dotenv').config()
+}
+const express = require('express')
+const routes = require('./routes')
+const methodOverride = require('method-override')
+const passport = require('./config/passport')
+const cors = require('cors')
const app = express()
-const port = 3000
-// use helpers.getUser(req) to replace req.user
-function authenticated(req, res, next){
- // passport.authenticate('jwt', { ses...
-};
+// create socket.io server
+const { createServer } = require('http')
+const httpServer = createServer(app)
+const io = require('socket.io')(httpServer, {
+ cors: {
+ origin: '*',
+ credentials: true
+ }
+})
+const useSocket = require('./socket/index')
+const port = process.env.PORT || 3000
+
+// middleware
+app.use(express.urlencoded({ extended: true }))
+app.use(express.json())
+app.use(passport.initialize())
+app.use(methodOverride('_method'))
+
+// cors
+app.use(
+ cors({
+ // origin: 'https://zebrrrra.github.io',
+ origin: '*',
+ credentials: true,
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']
+ })
+)
+
+// routes
+app.get('/', (req, res) => { res.send('Welcome to the real world!') })
+app.use(routes)
+
+// use socket modules
+useSocket(io)
-app.get('/', (req, res) => res.send('Hello World!'))
-app.listen(port, () => console.log(`Example app listening on port ${port}!`))
+// start
+httpServer.listen(port, () => console.log(`Example app listening on port ${port}!`))
module.exports = app
diff --git a/config/config.json b/config/config.json
index 8920098a42..44cbfe8929 100644
--- a/config/config.json
+++ b/config/config.json
@@ -15,11 +15,7 @@
"logging": false
},
"production": {
- "username": "root",
- "password": null,
- "database": "database_production",
- "host": "127.0.0.1",
- "dialect": "mysql"
+ "use_env_variable": "CLEARDB_DATABASE_URL"
},
"travis": {
"username": "travis",
diff --git a/config/passport.js b/config/passport.js
index a2298f8964..1e7c87f2de 100644
--- a/config/passport.js
+++ b/config/passport.js
@@ -1,5 +1,9 @@
const passport = require('passport')
+const LocalStrategy = require('./strategies/local')
+const JtwStrategy = require('./strategies/jwt')
+// strategy
+LocalStrategy(passport)
+JtwStrategy(passport)
-
-module.exports = passport
\ No newline at end of file
+module.exports = passport
diff --git a/config/strategies/jwt.js b/config/strategies/jwt.js
new file mode 100644
index 0000000000..d1d4eb4f8a
--- /dev/null
+++ b/config/strategies/jwt.js
@@ -0,0 +1,22 @@
+const { User } = require('../../models')
+const passportJWT = require('passport-jwt')
+const JwtStrategy = passportJWT.Strategy
+const ExtractJwt = passportJWT.ExtractJwt
+
+const jwtOptions = {
+ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
+ secretOrKey: process.env.JWT_SECRET
+}
+
+module.exports = passport => {
+ // 認證JWT
+ passport.use(new JwtStrategy(jwtOptions, (jwtPayload, done) => {
+ User.findByPk(jwtPayload.id, {
+ })
+ .then(user => {
+ if (!user) return done(null, false)
+ return done(null, user)
+ })
+ .catch(err => done(err))
+ }))
+}
diff --git a/config/strategies/local.js b/config/strategies/local.js
new file mode 100644
index 0000000000..5fdef80781
--- /dev/null
+++ b/config/strategies/local.js
@@ -0,0 +1,32 @@
+const LocalStrategy = require('passport-local')
+const { User } = require('../../models')
+const bcrypt = require('bcryptjs')
+
+module.exports = passport => {
+ passport.use(new LocalStrategy({
+ usernameField: 'account',
+ passwordField: 'password'
+ }, (account, password, done) => {
+ // use email to check user exist
+ // 查出使用者資料,放入req.user
+ User.findOne({ where: { account } })
+ .then(user => {
+ if (!user) {
+ const error = new Error('帳號不存在!')
+ error.status = 401
+ return done(error, false)
+ }
+ // compare password
+ bcrypt.compare(password, user.password).then(isMatch => {
+ if (!isMatch) {
+ const error = new Error('帳號或是密碼錯誤!')
+ error.status = 401
+ return done(error, false)
+ }
+ // authenticated, return user
+ return done(null, user.get())
+ })
+ .catch(err => done(err, false))
+ })
+ }))
+}
diff --git a/controllers/admin-controller.js b/controllers/admin-controller.js
new file mode 100644
index 0000000000..7db1b79cb6
--- /dev/null
+++ b/controllers/admin-controller.js
@@ -0,0 +1,191 @@
+const jwt = require('jsonwebtoken')
+const db = require('../models')
+const { User, Tweet, Like, Reply } = db
+const sequelize = require('sequelize')
+const helpers = require('../_helpers')
+
+const adminController = {
+ login: (req, res, next) => {
+ try {
+ // 製作token給管理員
+ const userData = req.user
+ delete userData.password
+ const token = jwt.sign(userData, process.env.JWT_SECRET, {
+ expiresIn: '30d'
+ })
+ res.status(200).json({
+ status: 'success',
+ data: {
+ token,
+ user: userData
+ }
+ })
+ } catch (err) {
+ next(err)
+ }
+ },
+ getUsers: async (req, res, next) => {
+ try {
+ const users = await User.findAll({
+ attributes: {
+ exclude: ['password'],
+ include: [
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Followships WHERE followingId = User.id)'
+ ),
+ 'followersCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Followships WHERE followerId = User.id)'
+ ),
+ 'followingsCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Tweets WHERE UserId = User.id)'
+ ),
+ 'tweetsCount'
+ ]
+ // ,[
+ // sequelize.literal(
+ // '(SELECT COUNT(*) FROM likes l INNER JOIN tweets t on l.TweetId = t.id where t.UserId = User.id)'
+ // ),
+ // 'receivedLikesCount'
+ // ]
+ ]
+ },
+ order: [[sequelize.literal('TweetsCount'), 'DESC']]
+ })
+
+ // reorganize users data
+ const usersData = users.map(user => {
+ const userData = user.toJSON()
+ return {
+ ...userData
+ }
+ })
+
+ res.status(200).json(usersData)
+ } catch (err) {
+ next(err)
+ }
+ },
+ getTweets: async (req, res, next) => {
+ try {
+ const currentUserId = helpers.getUser(req).id
+ const tweets = await Tweet.findAll({
+ attributes: {
+ include: [
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Replies WHERE TweetId = Tweet.id)'
+ ),
+ 'repliesCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Likes WHERE TweetId = Tweet.id)'
+ ),
+ 'likesCount'
+ ]
+ ]
+ },
+ include: [
+ {
+ model: User,
+ attributes: { exclude: ['password'] }
+ },
+ {
+ model: Like,
+ attributes: ['UserId']
+ }
+ ],
+ order: [['createdAt', 'DESC']]
+ })
+ if (!tweets) throw new Error('找不到tweets資料!')
+ // 回傳全部tweet,最新的在前面
+ const tweetsData = tweets.map(tweet => ({
+ ...tweet.toJSON(),
+ isCurrentUserLiked: tweet.Likes.some(
+ like => like.UserId === currentUserId
+ )
+ }))
+
+ res.json(tweetsData)
+ } catch (err) {
+ next(err)
+ }
+ },
+ deleteTweet: async (req, res, next) => {
+ try {
+ // 確認是否為admin身分
+ const isCurrentUserAdim = helpers.getUser(req).role === 'admin'
+ if (!isCurrentUserAdim) throw new Error('您沒有權限刪除推文')
+
+ const tweet = await Tweet.findByPk(req.params.id)
+ if (!tweet) throw new Error('推文不存在!')
+ await Reply.destroy({ where: { TweetId: req.params.id } })
+ await Like.destroy({ where: { TweetId: req.params.id } })
+
+ await tweet.destroy()
+ res.status(200).json({
+ status: 'success',
+ message: '成功刪除推文'
+ })
+ } catch (err) {
+ next(err)
+ }
+ },
+ getUsersData: async (req, res, next) => {
+ try {
+ const users = await User.findAll({
+ attributes: {
+ exclude: ['password'],
+ include: [
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Followships WHERE followingId = User.id)'
+ ),
+ 'followersCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Followships WHERE followerId = User.id)'
+ ),
+ 'followingsCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Tweets WHERE UserId = User.id)'
+ ),
+ 'tweetsCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM likes l INNER JOIN tweets t on l.TweetId = t.id where t.UserId = User.id)'
+ ),
+ 'receivedLikesCount'
+ ]
+ ]
+ },
+ order: [[sequelize.literal('TweetsCount'), 'DESC']]
+ })
+
+ // reorganize users data
+ const usersData = users.map(user => {
+ const userData = user.toJSON()
+ return {
+ ...userData
+ }
+ })
+
+ res.status(200).json(usersData)
+ } catch (err) {
+ next(err)
+ }
+ }
+}
+
+module.exports = adminController
diff --git a/controllers/followship-controller.js b/controllers/followship-controller.js
new file mode 100644
index 0000000000..823ac96d35
--- /dev/null
+++ b/controllers/followship-controller.js
@@ -0,0 +1,61 @@
+const db = require('../models')
+const { Followship, User } = db
+const helpers = require('../_helpers')
+
+const followshipController = {
+
+ postFollowship: async (req, res, next) => {
+ try {
+ // 確認要追隨的人存不存在 (不能追隨管理者跟自己)
+ const followerId = helpers.getUser(req).id.toString()
+ const followingId = req.body.id
+
+ if (!followingId) throw new Error('請輸入要追隨人的id!')
+ if (followerId === followingId) throw new Error('不能追隨自己!')
+
+ const following = await User.findByPk(followingId, {
+ where: { role: 'user' }
+ })
+ if (!following) throw new Error('你要追隨的使用者不存在!')
+
+ // 確認沒有這個followship
+ const followship = await Followship.findOne({
+ where: { followerId, followingId }
+ })
+ if (followship) throw new Error('已經在追隨這個使用者了!')
+
+ // 建立兩人關西
+ await Followship.create({ followerId, followingId })
+ res.json({
+ status: 'success',
+ message: '成功追隨使用者!'
+ })
+ } catch (error) {
+ next(error)
+ }
+ },
+ deleteFollowship: async (req, res, next) => {
+ try {
+ // 確認沒有這個followship
+ const followerId = helpers.getUser(req).id.toString()
+ const followingId = req.params.followingId
+
+ if (followerId === followingId) throw new Error('不能取消追隨自己!')
+ const followship = await Followship.findOne({
+ where: { followingId, followerId }
+ })
+ if (!followship) throw new Error('你沒有在追蹤這位使用者')
+
+ // 刪除
+ await followship.destroy()
+ res.json({
+ status: 'success',
+ message: '成功取消追隨該使用者!'
+ })
+ } catch (error) {
+ next(error)
+ }
+ }
+}
+
+module.exports = followshipController
diff --git a/controllers/tweet-controller.js b/controllers/tweet-controller.js
new file mode 100644
index 0000000000..790a3730a2
--- /dev/null
+++ b/controllers/tweet-controller.js
@@ -0,0 +1,237 @@
+const db = require('../models')
+const { User, Tweet, Reply, Like } = db
+const sequelize = require('sequelize')
+const helpers = require('../_helpers')
+const { raw } = require('body-parser')
+
+const tweetController = {
+ getTweets: async (req, res, next) => {
+ try {
+ const currentUserId = helpers.getUser(req).id
+ const tweets = await Tweet.findAll({
+ attributes: {
+ include: [
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Replies WHERE TweetId = Tweet.id)'
+ ), 'repliesCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Likes WHERE TweetId = Tweet.id)'
+ ), 'likesCount'
+ ]
+ ]
+ },
+ include: [
+ {
+ model: User,
+ attributes: { exclude: ['password'] }
+ },
+ {
+ model: Like,
+ attributes: ['UserId']
+ }
+ ],
+ order: [['createdAt', 'DESC']]
+ })
+ if (!tweets) throw new Error('找不到tweets資料!')
+ // 回傳全部tweet,最新的在前面
+ const tweetsData = tweets.map(tweet => ({
+ ...tweet.toJSON(),
+ isCurrentUserLiked: tweet.Likes.some(like => like.UserId === currentUserId)
+ }))
+
+ res.json(tweetsData)
+ } catch (err) {
+ next(err)
+ }
+ },
+ getTweet: async (req, res, next) => {
+ try {
+ const currentUserId = helpers.getUser(req).id
+ const tweetId = req.params.tweetId
+ const tweet = await Tweet.findByPk(tweetId, {
+ attributes: {
+ include: [
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Replies WHERE TweetId = Tweet.id)'
+ ),
+ 'repliesCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Likes WHERE TweetId = Tweet.id )'
+ ),
+ 'likesCount'
+ ]
+ ]
+ },
+ include: [
+ {
+ model: User,
+ attributes: { exclude: ['password'] }
+ },
+ {
+ model: Reply,
+ order: [['createdAt', 'DESC']]
+ },
+ {
+ model: Like,
+ attributes: ['UserId']
+ }
+ ],
+ nest: true
+ })
+ if (!tweet) throw new Error('找不到tweet資料!')
+ // 回傳一則tweet
+ const tweetData = {
+ ...tweet.toJSON(),
+ isCurrentUserLiked: tweet.Likes.some(like => like.UserId === currentUserId)
+ }
+
+ res.json(tweetData)
+ } catch (err) {
+ next(err)
+ }
+ },
+ postTweet: async (req, res, next) => {
+ try {
+ const { description } = req.body
+ if (!description) throw new Error('請輸入內容!')
+ if (description.length > 140) throw new Error('內容限制為140字以內!')
+ await Tweet.create({
+ UserId: helpers.getUser(req).id,
+ description
+ })
+ // 回傳成功訊息
+ res.json({
+ status: 'success',
+ message: '成功建立Tweet'
+ })
+ } catch (err) {
+ next(err)
+ }
+ },
+ postReply: async (req, res, next) => {
+ try {
+ const tweetId = req.params.tweetId
+ const { comment } = req.body
+ if (!comment) throw new Error('請輸入內容!')
+ await Reply.create({
+ UserId: helpers.getUser(req).id,
+ TweetId: tweetId,
+ comment
+ })
+ res.json({
+ status: 'success', message: '成功建立留言'
+ })
+ } catch (error) {
+ next(error)
+ }
+ },
+ getReplies: async (req, res, next) => {
+ try {
+ console.log('getReplies')
+
+ const tweetId = req.params.tweetId
+
+ // // 推文擁有者
+ // const tweet = await Tweet.findByPk(tweetId, {
+ // attributes: [],
+ // include: {
+ // model: User,
+ // attributes: ['id', 'account', 'name', 'avatar']
+ // },
+ // nest: true,
+ // raw: true
+ // })
+
+ // // 回覆 + 回覆者
+ // const replies = await Reply.findAll({
+ // where: { TweetId: tweetId },
+ // include: [
+ // { model: User, attributes: { exclude: ['password'] } }
+ // ],
+ // order: [['createdAt', 'DESC']],
+ // raw: true,
+ // nest: true
+ // })
+
+ const replies = await Reply.findAll({
+ where: { TweetId: tweetId },
+ include: [
+ {
+ model: User,
+ attributes: ['id', 'account', 'name', 'avatar'],
+ },
+ {
+ model: Tweet,
+ attributes: [],
+ where: { id: tweetId },
+ include: [
+ {
+ model: User,
+ attributes: ['id', 'account', 'name', 'avatar'],
+ }
+ ]
+ }
+ ],
+ order: [['createdAt', 'DESC']],
+ raw: true,
+ nest: true
+ })
+
+ res.json(replies)
+ } catch (error) {
+ next(error)
+ }
+ },
+ postLike: async (req, res, next) => {
+ try {
+ const TweetId = req.params.tweetId
+ const UserId = helpers.getUser(req).id
+
+ const like = await Like.findOne({
+ where: { TweetId, UserId }
+ })
+
+ // 已經有Like
+ if (like) throw new Error('已經Like過這篇推文了!')
+
+ // 不存在: 建立一個like
+ if (!like) await Like.create({ UserId, TweetId })
+ res.json({
+ status: 'success',
+ message: '成功按讚!'
+ })
+ } catch (error) {
+ next(error)
+ }
+ },
+ postUnlike: async (req, res, next) => {
+ try {
+ const TweetId = req.params.tweetId
+ const UserId = helpers.getUser(req).id
+
+ const like = await Like.findOne({
+ where: { TweetId, UserId }
+ })
+
+ // 不存在
+ if (!like) throw new Error('這篇推文不存在這個like!')
+
+ // 刪除 Like
+ await like.destroy()
+ res.json({
+ status: 'success',
+ message: '成功取消按讚!'
+ })
+ } catch (error) {
+ next(error)
+ }
+ }
+}
+
+module.exports = tweetController
diff --git a/controllers/user-controller.js b/controllers/user-controller.js
new file mode 100644
index 0000000000..4fe6ea4d77
--- /dev/null
+++ b/controllers/user-controller.js
@@ -0,0 +1,442 @@
+const jwt = require('jsonwebtoken')
+const bcrypt = require('bcryptjs')
+const db = require('../models')
+const { Op } = require('sequelize')
+const { User, Tweet, Reply, Like, Followship } = db
+const sequelize = require('sequelize')
+const helpers = require('../_helpers')
+const { imgurFileHandler } = require('../helpers/file-helpers')
+
+const userController = {
+ login: (req, res, next) => {
+ try {
+ // 製作token給使用者
+ const userData = req.user
+ delete userData.password
+
+ const token = jwt.sign(userData, process.env.JWT_SECRET, {
+ expiresIn: '30d'
+ })
+ res.status(200).json({
+ status: 'success',
+ data: {
+ token,
+ user: userData
+ }
+ })
+ } catch (err) {
+ next(err)
+ }
+ },
+ signup: async (req, res, next) => {
+ try {
+ // 註冊時,使用者可以設定 account、name、email 和 password
+ const { account, name, email, password, checkPassword } = req.body
+ if (!account.trim() || !name.trim() || !email.trim() || !password.trim() || !checkPassword.trim()) throw new Error('請輸入完整資訊!')
+
+ // check name 不能超過50字
+ if (name.length > 50) throw new Error('name 超過字數限制50字元!')
+
+ // check password
+ if (password !== checkPassword) throw new Error('密碼不相同!')
+
+ // 檢查account, email 是否重複
+ const user = await User.findOne({
+ where: {
+ [Op.or]: [
+ { email: email },
+ { account: account }
+ ]
+ }
+ })
+ if (user?.account === account) throw new Error('account 已重複註冊!')
+ if (user?.email === email) throw new Error('email 已重複註冊!')
+ // 創立新使用者
+ await User.create({
+ account,
+ name,
+ email,
+ password: bcrypt.hashSync(password),
+ role: 'user',
+ createAt: new Date(),
+ updatedAt: new Date()
+ })
+ // 回傳成功訊息
+ res.json({
+ status: 'success', message: '成功建立帳號'
+ })
+ } catch (err) {
+ next(err)
+ }
+ },
+ getUserData: async (req, res, next) => {
+ try {
+ const currentUserId = helpers.getUser(req).id
+ const user = await User.findByPk(req.params.id, {
+ attributes: {
+ exclude: ['password'],
+ include: [
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Followships WHERE followingId = User.id)'
+ ),
+ 'followersCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Followships WHERE followerId = User.id)'
+ ),
+ 'followingsCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Tweets WHERE UserId = User.id)'
+ ),
+ 'tweetsCount'
+ ]
+ ]
+ }
+ })
+ const followers = await Followship.findOne({
+ where: {
+ followingId: req.params.id,
+ followerId: currentUserId
+ }
+ })
+ if (!user) throw new Error('使用者不存在!')
+ // reorganize user data
+ const userData = {
+ ...user.toJSON(),
+ isCurrentUserFollowed: !!followers
+ }
+ res.status(200).json(userData)
+ } catch (err) { next(err) }
+ },
+ getUserTweets: async (req, res, next) => {
+ try {
+ const currentUserId = helpers.getUser(req).id
+ const tweets = await Tweet.findAll({
+ where: { UserId: req.params.id },
+ include: [
+ { model: User, attributes: { exclude: ['password'] } },
+ { model: Like, attributes: ['UserId'] }
+ ],
+ order: [['createdAt', 'DESC']],
+ nest: true,
+ attributes: {
+ include: [
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Replies WHERE TweetId = Tweet.id)'
+ ),
+ 'repliesCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Likes WHERE TweetId = Tweet.id)'
+ ),
+ 'likesCount'
+ ]
+ ]
+ }
+ })
+
+ const tweetsData = tweets.map(tweet => ({
+ ...tweet.toJSON(),
+ isCurrentUserLiked: tweet.Likes.some(like => like.UserId.toString() === currentUserId.toString())
+ }))
+ res.status(200).json(tweetsData)
+ } catch (err) {
+ next(err)
+ }
+ },
+ getUserReplies: async (req, res, next) => {
+ try {
+ const replies = await Reply.findAll({
+ where: { UserId: req.params.id },
+ include: [
+ { model: User, attributes: { exclude: ['password'] } },
+ {
+ model: Tweet,
+ include: [
+ { model: User, attributes: ['id', 'account', 'name', 'avatar'] }
+ ]
+ }
+ ],
+ order: [['createdAt', 'DESC']]
+ })
+
+ const repliesData = replies.map(reply => reply.toJSON())
+ res.status(200).json(repliesData)
+ } catch (err) {
+ next(err)
+ }
+ },
+ getUserLikes: async (req, res, next) => {
+ try {
+ const currentUserId = helpers.getUser(req).id
+
+ const likes = await Like.findAll({
+ where: {
+ UserId: req.params.id
+ },
+ // user story規定用likes記錄成立時間排序
+ order: [['createdAt', 'DESC']],
+ include: [
+ {
+ model: Tweet,
+ include: [
+ {
+ model: User,
+ attributes: ['id', 'account', 'name', 'avatar']
+ }],
+ attributes: {
+ include: [
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Replies WHERE TweetId = Tweet.id)'
+ ),
+ 'repliesCount'
+ ],
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) FROM Likes WHERE TweetId = Tweet.id)'
+ ),
+ 'likesCount'
+ ]
+ ]
+ }
+ }]
+ })
+ // 原本邏輯是這個 like 是不是 token user點選的,所以會有問題
+ // 查看token 使用者有沒有喜歡這個 tweet
+ const currentUserLikeTweets = await Like.findAll({
+ attributes: ['TweetId'],
+ where: [
+ { UserId: currentUserId }
+ ],
+ raw: true
+ })
+ const currentUserLikeTweetsId = currentUserLikeTweets.map(tweet => tweet.TweetId)
+
+ const likesData = likes.map(like => ({
+ ...like.toJSON(),
+ isCurrentUserLiked: currentUserLikeTweetsId.some(id => id.toString() === like.Tweet.id.toString())
+ }))
+ res.status(200).json(likesData)
+ } catch (err) {
+ next(err)
+ }
+ },
+ getFollowings: async (req, res, next) => {
+ try {
+ const currentUserId = helpers.getUser(req).id
+
+ // 指定的使用者(:id)
+ const user = await User.findByPk(req.params.id, {
+ attributes: { exclude: ['password'] }
+ })
+ if (!user) throw new Error('使用者不存在!')
+
+ // 指定的使用者(:id)正在追蹤的對象
+ const followings = await Followship.findAll({
+ where: { followerId: req.params.id },
+ include: [
+ {
+ model: User,
+ as: 'Following',
+ attributes: {
+ exclude: ['password'],
+ include: [
+ // 查詢token user 有沒有追隨這位 Following
+ [
+ sequelize.literal('(SELECT CASE WHEN EXISTS(SELECT * FROM Followships WHERE followerId = ' + currentUserId + ' AND followingId = Following.id) THEN "true" ELSE "false" END)'), 'isCurrentUserFollowed'
+ ]
+ ]
+ }
+ }
+ ],
+ order: [['createdAt', 'DESC']]
+ })
+
+ const followingsData = followings.map(following => ({
+ ...following.toJSON()
+ }))
+ res.status(200).json(followingsData)
+ } catch (err) {
+ next(err)
+ }
+ },
+ getFollowers: async (req, res, next) => {
+ try {
+ const currentUserId = helpers.getUser(req).id
+
+ // 指定的使用者(:id)
+ const user = await User.findByPk(req.params.id, {
+ attributes: { exclude: ['password'] }
+ })
+ if (!user) throw new Error('使用者不存在!')
+
+ // 正在追蹤指定的使用者(:id)的使用者
+ const followers = await Followship.findAll({
+ where: { followingId: req.params.id },
+ include: [
+ {
+ model: User,
+ as: 'Follower',
+ attributes: {
+ exclude: ['password'],
+ include: [
+ // 查詢token user 有沒有追隨這位 Follower
+ [
+ sequelize.literal('(SELECT CASE WHEN EXISTS(SELECT * FROM Followships WHERE followerId = ' + currentUserId + ' AND followingId = Follower.id) THEN "true" ELSE "false" END)'), 'isCurrentUserFollowed'
+ ]
+ ]
+ }
+ }
+ ],
+ order: [['createdAt', 'DESC']]
+ })
+
+ const followersData = followers.map(follower => ({
+ ...follower.toJSON()
+ }))
+ res.status(200).json(followersData)
+ } catch (err) {
+ next(err)
+ }
+ },
+ putUserSetting: async (req, res, next) => {
+ try {
+ // 使用者僅能編輯自己的資料
+ const currentUser = helpers.getUser(req)
+ const currentUserId = helpers.getUser(req).id
+ if (currentUserId.toString() !== req.params.id) { throw new Error('你沒有權限可以編輯他人資料') }
+
+ // 使用者能編輯自己的 account、name、email 和 password
+ const { account, name, email, password, checkPassword, introduction } = req.body
+
+ // 暱稱上限 50 字
+ if (name && name.length > 50) throw new Error('name 超過字數限制50字元!')
+
+ // 自我介紹上限 160字
+ if (introduction && introduction.length > 160) { throw new Error('introduction 超過字數限制160字元!') }
+
+ // check password
+ if (password !== checkPassword) throw new Error('密碼不相同')
+
+ // 檢查account, email 是否重複
+ if (email || account) {
+ const checkUser = await User.findOne({
+ where: {
+ [Op.or]: [email ? { email } : {}, account ? { account } : {}],
+ id: {
+ [Op.not]: currentUserId
+ }
+ }
+ })
+
+ if (checkUser?.account === account) throw new Error('account 已重複註冊!')
+ if (checkUser?.email === email) throw new Error('email 已重複註冊!')
+ }
+
+ const user = await User.findByPk(req.params.id)
+ // 更新使用者資訊
+ await user.update({
+ account: account || user.account,
+ name: name || user.name,
+ email: email || user.email,
+ password: password ? bcrypt.hashSync(password) : user.password,
+ introduction: introduction || user.introduction
+ })
+
+ // 回傳成功訊息
+ res.status(200).json({
+ status: 'success',
+ message: '成功編輯帳號資訊'
+ })
+ } catch (err) {
+ next(err)
+ }
+ },
+ putUserProfile: async (req, res, next) => {
+ try {
+ // 使用者僅能編輯自己的資料
+ const currentUserId = helpers.getUser(req).id
+ if (currentUserId.toString() !== req.params.id) {
+ throw new Error('你沒有權限可以編輯他人資料')
+ }
+ const { name, introduction } = req.body
+ const { files } = req
+
+ // 自我介紹字數上限 160 字、暱稱上限 50 字
+ if (name && name.length > 50) throw new Error('name 超過字數限制50字元!')
+ if (introduction && introduction.length > 160) { throw new Error(' introduction 超過字數限制160字元!') }
+
+ const user = await User.findByPk(req.params.id)
+ if (!user) throw new Error('使用者不存在!')
+
+ const avatar = files?.avatar ? await imgurFileHandler(files.avatar[0]) : null
+
+ const cover = files?.cover ? await imgurFileHandler(files.cover[0]) : null
+
+ await user.update({
+ name: name || user.name,
+ introduction: introduction || user.introduction,
+ avatar: avatar || user.avatar,
+ cover: cover || user.cover
+ })
+
+ res.status(200).json({
+ status: 'success',
+ message: '成功編輯使用者Profile'
+ })
+ } catch (err) {
+ next(err)
+ }
+ },
+ getTopFollower: async (req, res, next) => {
+ try {
+ // get current login user data
+ const currentUserId = helpers.getUser(req).id
+ // find top 10 followers users
+ const users = await User.findAll({
+ attributes: {
+ exclude: ['password'],
+ include: [
+ [
+ sequelize.literal(
+ '(SELECT COUNT(*) as followersCount FROM Followships WHERE followingId = User.id ORDER BY followersCount)'
+ ),
+ 'followersCount'
+ ]
+ ]
+ },
+ include: {
+ model: User,
+ as: 'Followers',
+ attributes: ['id']
+ },
+ // 排除目前的使用者
+ where: {
+ id: { [sequelize.Op.not]: currentUserId },
+ role: { [sequelize.Op.not]: 'admin' }
+ },
+ order: [
+ [sequelize.literal('followersCount'), 'DESC']
+ ],
+ limit: 10
+ })
+
+ // reorganize user data
+ const topUsersData = users.map(user => ({
+ ...user.toJSON(),
+ isCurrentUserFollowed: user.Followers.map(follower => follower.id).some(id => id.toString() === currentUserId.toString())
+ }))
+ res.status(200).json(topUsersData)
+ } catch (err) {
+ next(err)
+ }
+ }
+}
+module.exports = userController
diff --git a/helpers/file-helpers.js b/helpers/file-helpers.js
new file mode 100644
index 0000000000..c9ba6feb17
--- /dev/null
+++ b/helpers/file-helpers.js
@@ -0,0 +1,18 @@
+const imgur = require('imgur')
+const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID
+imgur.setClientId(IMGUR_CLIENT_ID)
+
+const imgurFileHandler = file => {
+ return new Promise((resolve, reject) => {
+ if (!file) return resolve(null)
+ return imgur
+ .uploadFile(file.path)
+ .then(img => {
+ resolve(img?.link || null) // 檢查 img 是否存在
+ })
+ .catch(err => reject(err))
+ })
+}
+module.exports = {
+ imgurFileHandler
+}
diff --git a/middleware/auth.js b/middleware/auth.js
new file mode 100644
index 0000000000..bbfbe3e4d7
--- /dev/null
+++ b/middleware/auth.js
@@ -0,0 +1,14 @@
+const passport = require('passport')
+
+function authenticated (req, res, next) {
+ passport.authenticate('jwt', { session: false }, (err, user) => {
+ if (err || !user) return res.status(401).json({ status: 'error', message: 'unauthorized' })
+
+ req.user = user
+ next()
+ })(req, res, next) // invoke function
+}
+
+module.exports = {
+ authenticated
+}
diff --git a/middleware/error-handler.js b/middleware/error-handler.js
new file mode 100644
index 0000000000..ad8c4834ae
--- /dev/null
+++ b/middleware/error-handler.js
@@ -0,0 +1,9 @@
+module.exports = {
+ apiErrorHandler (err, req, res, next) {
+ const code = err.status || 500
+ res.status(code).json({
+ status: 'error',
+ message: `${err.message}`
+ })
+ }
+}
diff --git a/middleware/multer.js b/middleware/multer.js
new file mode 100644
index 0000000000..a1f175c498
--- /dev/null
+++ b/middleware/multer.js
@@ -0,0 +1,8 @@
+const multer = require('multer')
+const upload = multer({ dest: 'temp/' })
+const multiUpload = upload.fields([
+ { name: 'avatar', maxCount: 1 }, { name: 'cover', maxCount: 1 }])
+module.exports = {
+ upload,
+ multiUpload
+}
diff --git a/middleware/role-check.js b/middleware/role-check.js
new file mode 100644
index 0000000000..f15c4e45ac
--- /dev/null
+++ b/middleware/role-check.js
@@ -0,0 +1,20 @@
+const helpers = require('../_helpers') // for test
+const roleCheck = (role, errorMessage) => {
+ return (req, res, next) => {
+ if (helpers.getUser(req).role !== role) {
+ const error = new Error(errorMessage)
+ return res.status(401).json({
+ status: 'error',
+ message: error.message
+ })
+ }
+ next()
+ }
+}
+
+module.exports = {
+ isUser: roleCheck('user', '帳號不存在!'),
+ isAdmin: roleCheck('admin', '帳號不存在!'),
+ isAuthUser: roleCheck('user', '請先登入帳號!'),
+ isAuthAdmin: roleCheck('admin', '請先登入帳號!')
+}
diff --git a/migrations/20190115071418-create-followship.js b/migrations/20190115071418-create-followship.js
index 4e04770a7c..ca5835b907 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', {
@@ -22,9 +22,9 @@ module.exports = {
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 08c9e524d5..11b8ea2452 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', {
@@ -22,9 +22,9 @@ module.exports = {
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 ccfd119c53..5ffffab111 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', {
@@ -25,9 +25,9 @@ module.exports = {
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 201c8e8245..1abc04a36e 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', {
@@ -22,9 +22,9 @@ module.exports = {
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 2376dbb50d..43144b48f3 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', {
@@ -11,19 +11,29 @@ module.exports = {
email: {
type: Sequelize.STRING
},
- password: {
+ account: {
type: Sequelize.STRING
},
name: {
type: Sequelize.STRING
},
- avatar: {
- type: Sequelize.STRING
+ role: {
+ type: Sequelize.STRING,
+ allowNull: false,
+ defaultValue: 'user'
},
introduction: {
type: Sequelize.TEXT
},
- role: {
+ avatar: {
+ type: Sequelize.STRING,
+ defaultValue: 'https://i.imgur.com/PiJ0HXw.png'
+ },
+ cover: {
+ type: Sequelize.STRING,
+ defaultValue: 'https://i.imgur.com/xZoHPfC.png'
+ },
+ password: {
type: Sequelize.STRING
},
createdAt: {
@@ -34,9 +44,9 @@ module.exports = {
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/migrations/20230703020921-create-room.js b/migrations/20230703020921-create-room.js
new file mode 100644
index 0000000000..1515609159
--- /dev/null
+++ b/migrations/20230703020921-create-room.js
@@ -0,0 +1,30 @@
+'use strict'
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.createTable('Rooms', {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ userOneId: {
+ type: Sequelize.INTEGER
+ },
+ userTwoId: {
+ type: Sequelize.INTEGER
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ }
+ })
+ },
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.dropTable('Rooms')
+ }
+}
diff --git a/migrations/20230703023402-create-chat.js b/migrations/20230703023402-create-chat.js
new file mode 100644
index 0000000000..50765d8eb8
--- /dev/null
+++ b/migrations/20230703023402-create-chat.js
@@ -0,0 +1,36 @@
+'use strict'
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ return queryInterface.createTable('Chats', {
+ id: {
+ allowNull: false,
+ autoIncrement: true,
+ primaryKey: true,
+ type: Sequelize.INTEGER
+ },
+ message: {
+ type: Sequelize.TEXT
+ },
+ userId: {
+ type: Sequelize.INTEGER
+ },
+ roomId: {
+ type: Sequelize.INTEGER
+ },
+ timestamp: {
+ type: Sequelize.DATE
+ },
+ createdAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ },
+ updatedAt: {
+ allowNull: false,
+ type: Sequelize.DATE
+ }
+ })
+ },
+ down: (queryInterface, Sequelize) => {
+ return queryInterface.dropTable('Chats')
+ }
+}
diff --git a/models/chat.js b/models/chat.js
new file mode 100644
index 0000000000..32febc5e65
--- /dev/null
+++ b/models/chat.js
@@ -0,0 +1,24 @@
+'use strict'
+const { Model } = require('sequelize')
+module.exports = (sequelize, DataTypes) => {
+ class Chat extends Model {
+ static associate (models) {
+ Chat.belongsTo(models.User, { foreignKey: 'userId' })
+ Chat.belongsTo(models.Room, { foreignKey: 'roomId' })
+ }
+ }
+ Chat.init(
+ {
+ message: DataTypes.STRING,
+ userId: DataTypes.INTEGER,
+ roomId: DataTypes.INTEGER,
+ timestamp: DataTypes.DATE // 訊息發送的時間
+ },
+ {
+ sequelize,
+ modelName: 'Chat',
+ tableName: 'Chats'
+ }
+ )
+ return Chat
+}
diff --git a/models/followship.js b/models/followship.js
index 790f3faa39..6ea7591c4a 100644
--- a/models/followship.js
+++ b/models/followship.js
@@ -1,8 +1,29 @@
-'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 {
+ static associate (models) {
+ Followship.belongsTo(models.User, {
+ as: 'Follower',
+ foreignKey: 'followerId'
+ })
+ Followship.belongsTo(models.User, {
+ as: 'Following',
+ foreignKey: 'followingId'
+ })
+ }
+ }
+ Followship.init(
+ {
+ followerId: DataTypes.INTEGER,
+ followingId: DataTypes.INTEGER
+ },
+ {
+ sequelize,
+ modelName: 'Followship',
+ tableName: 'Followships'
+ }
+ )
+ return Followship
+}
diff --git a/models/index.js b/models/index.js
index 33f09e7764..427848cb0b 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/models/like.js b/models/like.js
index c8939de1fc..4f5776e3fb 100644
--- a/models/like.js
+++ b/models/like.js
@@ -1,8 +1,23 @@
-'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 {
+ static associate (models) {
+ Like.belongsTo(models.Tweet, { foreignKey: 'TweetId' })
+ Like.belongsTo(models.User, { foreignKey: 'UserId' })
+ }
+ }
+ Like.init(
+ {
+ UserId: DataTypes.INTEGER,
+ TweetId: DataTypes.INTEGER
+ },
+ {
+ sequelize,
+ modelName: 'Like',
+ tableName: 'Likes'
+ }
+ )
+ return Like
+}
diff --git a/models/reply.js b/models/reply.js
index 60387f164f..a39a0e04b3 100644
--- a/models/reply.js
+++ b/models/reply.js
@@ -1,8 +1,24 @@
-'use strict';
+'use strict'
+const { Model } = require('sequelize')
+
module.exports = (sequelize, DataTypes) => {
- const Reply = sequelize.define('Reply', {
- }, {});
- Reply.associate = function(models) {
- };
- return Reply;
-};
\ No newline at end of file
+ class Reply extends Model {
+ static associate (models) {
+ Reply.belongsTo(models.Tweet, { foreignKey: 'TweetId' })
+ Reply.belongsTo(models.User, { foreignKey: 'UserId' })
+ }
+ }
+ Reply.init(
+ {
+ UserId: DataTypes.INTEGER,
+ TweetId: DataTypes.INTEGER,
+ comment: DataTypes.TEXT
+ },
+ {
+ sequelize,
+ modelName: 'Reply',
+ tableName: 'Replies'
+ }
+ )
+ return Reply
+}
diff --git a/models/room.js b/models/room.js
new file mode 100644
index 0000000000..854986d617
--- /dev/null
+++ b/models/room.js
@@ -0,0 +1,23 @@
+'use strict'
+const { Model } = require('sequelize')
+module.exports = (sequelize, DataTypes) => {
+ class Room extends Model {
+ static associate (models) {
+ Room.belongsTo(models.User, { foreignKey: 'userOneId' })
+ Room.belongsTo(models.User, { foreignKey: 'userTwoId' })
+ Room.hasMany(models.Chat, { foreignKey: 'roomId' })
+ }
+ }
+ Room.init(
+ {
+ userOneId: DataTypes.INTEGER,
+ userTwoId: DataTypes.INTEGER
+ },
+ {
+ sequelize,
+ modelName: 'Room',
+ tableName: 'Rooms'
+ }
+ )
+ return Room
+}
diff --git a/models/tweet.js b/models/tweet.js
index a8b6600778..8f25df949d 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 {
+ static associate (models) {
+ Tweet.belongsTo(models.User, { foreignKey: 'UserId' })
+ Tweet.hasMany(models.Reply, {
+ foreignKey: 'TweetId',
+ onDelete: 'CASCADE'
+ })
+ Tweet.hasMany(models.Like, {
+ foreignKey: 'TweetId',
+ onDelete: 'CASCADE'
+ })
+ }
+ }
+ Tweet.init(
+ {
+ UserId: DataTypes.INTEGER,
+ description: DataTypes.TEXT
+ },
+ {
+ sequelize,
+ modelName: 'Tweet',
+ tableName: 'Tweets'
+ }
+ )
+ return Tweet
+}
diff --git a/models/user.js b/models/user.js
index 82c5f84c83..d873c84f65 100644
--- a/models/user.js
+++ b/models/user.js
@@ -1,8 +1,43 @@
-'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 {
+ static associate (models) {
+ User.hasMany(models.Tweet, { foreignKey: 'UserId' })
+ User.hasMany(models.Reply, { foreignKey: 'UserId' })
+ User.hasMany(models.Like, { foreignKey: 'UserId' })
+
+ // the user's followers
+ User.belongsToMany(User, {
+ through: models.Followship,
+ foreignKey: 'followingId',
+ as: 'Followers'
+ })
+ // the user's followings
+ User.belongsToMany(User, {
+ through: models.Followship,
+ foreignKey: 'followerId',
+ as: 'Followings'
+ })
+ }
+ }
+ User.init(
+ {
+ email: DataTypes.STRING,
+ password: DataTypes.STRING,
+ name: DataTypes.STRING,
+ avatar: DataTypes.STRING,
+ introduction: DataTypes.TEXT,
+ role: DataTypes.STRING,
+ account: DataTypes.STRING,
+ cover: DataTypes.STRING
+ },
+ {
+ sequelize, // We need to pass the connection instance
+ modelName: 'User',
+ tableName: 'Users'
+ }
+ )
+ return User
+}
diff --git a/package-lock.json b/package-lock.json
index aa65e2e434..25e1f9dd0f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,183 +1,391 @@
{
"name": "test",
"version": "1.0.0",
- "lockfileVersion": 2,
+ "lockfileVersion": 1,
"requires": true,
- "packages": {
- "": {
- "name": "test",
- "version": "1.0.0",
- "license": "ISC",
+ "dependencies": {
+ "@babel/code-frame": {
+ "version": "7.12.11",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
+ "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
+ "dev": true
+ },
+ "@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@eslint/eslintrc": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
+ "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.1.1",
+ "espree": "^7.3.0",
+ "globals": "^13.9.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "strip-json-comments": "^3.1.1"
+ },
"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-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"
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ }
+ }
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
+ "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^1.2.0",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
},
- "devDependencies": {
- "proxyquire": "^2.1.3",
- "sequelize-test-helpers": "^1.4.2",
- "supertest": "^3.3.0"
+ "dependencies": {
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
}
},
- "node_modules/@sinonjs/commons": {
+ "@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "@sindresorhus/is": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
+ "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="
+ },
+ "@sinonjs/commons": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
"integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==",
- "dependencies": {
+ "requires": {
"type-detect": "4.0.8"
}
},
- "node_modules/@sinonjs/fake-timers": {
+ "@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": {
+ "requires": {
"@sinonjs/commons": "^1.7.0"
}
},
- "node_modules/@sinonjs/samsam": {
+ "@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": {
+ "requires": {
"@sinonjs/commons": "^1.6.0",
"lodash.get": "^4.4.2",
"type-detect": "^4.0.8"
}
},
- "node_modules/@sinonjs/text-encoding": {
+ "@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": {
+ "@socket.io/component-emitter": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
+ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
+ },
+ "@szmarczak/http-timer": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
+ "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
+ "requires": {
+ "defer-to-connect": "^2.0.0"
+ }
+ },
+ "@types/cacheable-request": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
+ "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
+ "requires": {
+ "@types/http-cache-semantics": "*",
+ "@types/keyv": "^3.1.4",
+ "@types/node": "*",
+ "@types/responselike": "^1.0.0"
+ }
+ },
+ "@types/cookie": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz",
+ "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q=="
+ },
+ "@types/cors": {
+ "version": "2.8.13",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz",
+ "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@types/debug": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
"integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==",
- "dependencies": {
+ "requires": {
"@types/ms": "*"
}
},
- "node_modules/@types/ms": {
+ "@types/http-cache-semantics": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
+ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
+ },
+ "@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "@types/keyv": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
+ "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@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": {
+ "@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": {
+ "@types/responselike": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
+ "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@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": {
+ "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": {
+ "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": {
+ "requires": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
}
},
- "node_modules/ansi-colors": {
+ "acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
- "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==",
- "engines": {
- "node": ">=6"
- }
+ "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw=="
},
- "node_modules/ansi-regex": {
+ "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"
- }
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
- "node_modules/ansi-styles": {
+ "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": {
+ "requires": {
"color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
}
},
- "node_modules/argparse": {
+ "append-field": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
+ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
+ },
+ "argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dependencies": {
+ "requires": {
"sprintf-js": "~1.0.2"
}
},
- "node_modules/array-flatten": {
+ "array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ }
+ },
+ "array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
- "node_modules/assertion-error": {
+ "array-includes": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
+ "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "get-intrinsic": "^1.1.3",
+ "is-string": "^1.0.7"
+ }
+ },
+ "array.prototype.flat": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
+ "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0"
+ }
+ },
+ "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": "*"
- }
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="
+ },
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
},
- "node_modules/asynckit": {
+ "asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
- "dev": true
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
- "node_modules/balanced-match": {
+ "available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
+ },
+ "balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
- "node_modules/bcrypt-nodejs": {
+ "base64id": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz",
+ "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog=="
+ },
+ "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"
+ "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs="
+ },
+ "bcryptjs": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
+ "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
},
- "node_modules/bluebird": {
+ "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": {
+ "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": {
+ "requires": {
"bytes": "3.1.2",
"content-type": "~1.0.4",
"debug": "2.6.9",
@@ -190,59 +398,113 @@
"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": {
+ "brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dependencies": {
+ "requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
- "node_modules/browser-stdout": {
+ "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": {
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
+ },
+ "buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+ },
+ "busboy": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
+ "integrity": "sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg==",
+ "requires": {
+ "dicer": "0.2.5",
+ "readable-stream": "1.1.x"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+ },
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+ }
+ }
+ },
+ "bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "engines": {
- "node": ">= 0.8"
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
+ },
+ "cacheable-lookup": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
+ "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="
+ },
+ "cacheable-request": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
+ "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
+ "requires": {
+ "clone-response": "^1.0.2",
+ "get-stream": "^5.1.0",
+ "http-cache-semantics": "^4.0.0",
+ "keyv": "^4.0.0",
+ "lowercase-keys": "^2.0.0",
+ "normalize-url": "^6.0.1",
+ "responselike": "^2.0.0"
}
},
- "node_modules/call-bind": {
+ "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": {
+ "requires": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/camelcase": {
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "engines": {
- "node": ">=6"
- }
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
- "node_modules/chai": {
+ "chai": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
"integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
- "dependencies": {
+ "requires": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
"deep-eql": "^3.0.1",
@@ -250,48 +512,38 @@
"loupe": "^2.3.1",
"pathval": "^1.1.1",
"type-detect": "^4.0.5"
- },
- "engines": {
- "node": ">=4"
}
},
- "node_modules/chalk": {
+ "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": {
+ "requires": {
"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"
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
}
},
- "node_modules/check-error": {
+ "check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
- "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
- "engines": {
- "node": "*"
- }
+ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
},
- "node_modules/cli-color": {
+ "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": {
+ "requires": {
"ansi-regex": "^2.1.1",
"d": "1",
"es5-ext": "^0.10.46",
@@ -300,3343 +552,1029 @@
"timers-ext": "^0.1.5"
}
},
- "node_modules/cliui": {
+ "cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
- "dependencies": {
+ "requires": {
"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",
+ "ansi-regex": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+ "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "clone-response": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
+ "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
+ "requires": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "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": {
+ "requires": {
"delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
}
},
- "node_modules/commander": {
+ "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": {
+ "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": {
+ "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": {
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "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": {
+ "requires": {
"ini": "^1.3.4",
"proto-list": "~1.2.1"
}
},
- "node_modules/connect-flash": {
+ "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"
- }
+ "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA="
},
- "node_modules/content-disposition": {
+ "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": {
+ "requires": {
"safe-buffer": "5.2.1"
- },
- "engines": {
- "node": ">= 0.6"
}
},
- "node_modules/content-type": {
+ "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"
- }
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
- "node_modules/cookie": {
+ "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"
- }
+ "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
},
- "node_modules/cookie-signature": {
+ "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": {
+ "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": {
+ "core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
- "dev": true
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ },
+ "cors": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "requires": {
+ "object-assign": "^4",
+ "vary": "^1"
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "dependencies": {
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ }
+ }
},
- "node_modules/d": {
+ "d": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
- "dependencies": {
+ "requires": {
"es5-ext": "^0.10.50",
"type": "^1.0.1"
}
},
- "node_modules/debug": {
+ "debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dependencies": {
+ "requires": {
"ms": "2.0.0"
}
},
- "node_modules/decamelize": {
+ "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"
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
+ },
+ "decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "requires": {
+ "mimic-response": "^3.1.0"
+ },
+ "dependencies": {
+ "mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="
+ }
}
},
- "node_modules/deep-eql": {
+ "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": {
+ "requires": {
"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": {
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "defer-to-connect": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="
+ },
+ "define-properties": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
+ "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
+ "requires": {
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/delayed-stream": {
+ "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"
- }
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
- "node_modules/denque": {
+ "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"
- }
+ "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw=="
},
- "node_modules/depd": {
+ "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"
- }
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
},
- "node_modules/destroy": {
+ "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"
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
+ },
+ "dicer": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
+ "integrity": "sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg==",
+ "requires": {
+ "readable-stream": "1.1.x",
+ "streamsearch": "0.1.2"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+ },
+ "readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+ }
}
},
- "node_modules/diff": {
+ "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"
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
}
},
- "node_modules/dottie": {
+ "dotenv": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
+ "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="
+ },
+ "dottie": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz",
"integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg=="
},
- "node_modules/editorconfig": {
+ "ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "editorconfig": {
"version": "0.15.3",
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
"integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==",
- "dependencies": {
+ "requires": {
"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"
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ }
}
},
- "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": {
+ "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": {
+ "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": {
+ "encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
- "engines": {
- "node": ">= 0.8"
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "engine.io": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.1.tgz",
+ "integrity": "sha512-mGqhI+D7YxS9KJMppR6Iuo37Ed3abhU8NdfgSvJSDUafQutrN+sPTncJYTyM9+tkhSmWodKtVYGPPHyXJEwEQA==",
+ "requires": {
+ "@types/cookie": "^0.4.1",
+ "@types/cors": "^2.8.12",
+ "@types/node": ">=10.0.0",
+ "accepts": "~1.3.4",
+ "base64id": "2.0.0",
+ "cookie": "~0.4.1",
+ "cors": "~2.8.5",
+ "debug": "~4.3.1",
+ "engine.io-parser": "~5.1.0",
+ "ws": "~8.11.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
}
},
- "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==",
+ "engine.io-parser": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.1.0.tgz",
+ "integrity": "sha512-enySgNiK5tyZFynt3z7iqBR+Bto9EVVVvDFuTT0ioHCGbzirZVGDGiQjZzEp8hWl6hd5FSVytJGuScX1C1C35w=="
+ },
+ "enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1"
+ },
"dependencies": {
+ "ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true
+ }
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.21.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
+ "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
+ "requires": {
+ "array-buffer-byte-length": "^1.0.0",
+ "available-typed-arrays": "^1.0.5",
"call-bind": "^1.0.2",
+ "es-set-tostringtag": "^2.0.1",
"es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.2.0",
"get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
"has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
"has-symbols": "^1.0.3",
- "internal-slot": "^1.0.3",
- "is-callable": "^1.2.4",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
"is-negative-zero": "^2.0.2",
"is-regex": "^1.1.4",
"is-shared-array-buffer": "^1.0.2",
"is-string": "^1.0.7",
+ "is-typed-array": "^1.1.10",
"is-weakref": "^1.0.2",
- "object-inspect": "^1.12.0",
+ "object-inspect": "^1.12.3",
"object-keys": "^1.1.1",
- "object.assign": "^4.1.2",
- "string.prototype.trimend": "^1.0.4",
- "string.prototype.trimstart": "^1.0.4",
- "unbox-primitive": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.7",
+ "string.prototype.trimend": "^1.0.6",
+ "string.prototype.trimstart": "^1.0.6",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.9"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "dependencies": {
+ "object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ }
+ }
}
},
- "node_modules/es-abstract/node_modules/object.assign": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
- "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
- "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"
+ "es-set-tostringtag": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
+ "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
+ "requires": {
+ "get-intrinsic": "^1.1.3",
+ "has": "^1.0.3",
+ "has-tostringtag": "^1.0.0"
}
},
- "node_modules/es-to-primitive": {
+ "es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "es-to-primitive": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dependencies": {
+ "requires": {
"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": {
+ "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": {
+ "requires": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
"next-tick": "^1.1.0"
- },
- "engines": {
- "node": ">=0.10"
}
},
- "node_modules/es6-iterator": {
+ "es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
- "dependencies": {
+ "requires": {
"d": "1",
"es5-ext": "^0.10.35",
"es6-symbol": "^3.1.1"
}
},
- "node_modules/es6-symbol": {
+ "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": {
+ "requires": {
"d": "^1.0.1",
"ext": "^1.1.2"
}
},
- "node_modules/es6-weak-map": {
+ "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": {
+ "requires": {
"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-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.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/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/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.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/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/ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
- },
- "node_modules/module-not-found-error": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz",
- "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=",
- "dev": true
- },
- "node_modules/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/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.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/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/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/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/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/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",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
- "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==",
- "requires": {
- "type-detect": "4.0.8"
- }
- },
- "@sinonjs/fake-timers": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz",
- "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==",
- "requires": {
- "@sinonjs/commons": "^1.7.0"
- }
- },
- "@sinonjs/samsam": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz",
- "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==",
- "requires": {
- "@sinonjs/commons": "^1.6.0",
- "lodash.get": "^4.4.2",
- "type-detect": "^4.0.8"
- }
- },
- "@sinonjs/text-encoding": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz",
- "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ=="
- },
- "@types/debug": {
- "version": "4.1.7",
- "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz",
- "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==",
- "requires": {
- "@types/ms": "*"
- }
- },
- "@types/ms": {
- "version": "0.7.31",
- "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",
- "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="
- },
- "@types/node": {
- "version": "17.0.24",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.24.tgz",
- "integrity": "sha512-aveCYRQbgTH9Pssp1voEP7HiuWlD2jW2BO56w+bVrJn04i61yh6mRfoKO6hEYQD9vF+W8Chkwc6j1M36uPkx4g=="
- },
- "@types/validator": {
- "version": "13.7.2",
- "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.2.tgz",
- "integrity": "sha512-KFcchQ3h0OPQgFirBRPZr5F/sVjxZsOrQHedj3zi8AH3Zv/hOLx2OLR4hxR5HcfoU+33n69ZuOfzthKVdMoTiw=="
- },
- "abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
- },
- "accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "requires": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- }
- },
- "ansi-colors": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
- "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw=="
- },
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
- },
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "requires": {
- "sprintf-js": "~1.0.2"
- }
- },
- "array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
- },
- "assertion-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
- "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="
- },
- "asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
- "dev": true
- },
- "balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
- },
- "bcrypt-nodejs": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz",
- "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs="
- },
- "bluebird": {
- "version": "3.7.2",
- "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
- "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
- },
- "body-parser": {
- "version": "1.20.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==",
- "requires": {
- "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"
- }
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "browser-stdout": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
- "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
- },
- "bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
- },
- "call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
- "requires": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
- }
- },
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
- },
- "chai": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
- "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
- "requires": {
- "assertion-error": "^1.1.0",
- "check-error": "^1.0.2",
- "deep-eql": "^3.0.1",
- "get-func-name": "^2.0.0",
- "loupe": "^2.3.1",
- "pathval": "^1.1.1",
- "type-detect": "^4.0.5"
- }
- },
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
- }
- },
- "check-error": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
- "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
- },
- "cli-color": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz",
- "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==",
- "requires": {
- "ansi-regex": "^2.1.1",
- "d": "1",
- "es5-ext": "^0.10.46",
- "es6-iterator": "^2.0.3",
- "memoizee": "^0.4.14",
- "timers-ext": "^0.1.5"
- }
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
- "cliui": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
- "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ },
+ "eslint": {
+ "version": "7.32.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz",
+ "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==",
+ "dev": true,
"requires": {
- "string-width": "^3.1.0",
- "strip-ansi": "^5.2.0",
- "wrap-ansi": "^5.1.0"
+ "@babel/code-frame": "7.12.11",
+ "@eslint/eslintrc": "^0.4.3",
+ "@humanwhocodes/config-array": "^0.5.0",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "enquirer": "^2.3.5",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^2.1.0",
+ "eslint-visitor-keys": "^2.0.0",
+ "espree": "^7.3.1",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.1.2",
+ "globals": "^13.6.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.0.4",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "progress": "^2.0.0",
+ "regexpp": "^3.1.0",
+ "semver": "^7.2.1",
+ "strip-ansi": "^6.0.0",
+ "strip-json-comments": "^3.1.0",
+ "table": "^6.0.9",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
},
"dependencies": {
"ansi-regex": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
- "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
},
- "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==",
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
"requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "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==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "semver": {
+ "version": "7.5.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
+ "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
}
},
"strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
"requires": {
- "ansi-regex": "^4.1.0"
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
}
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
}
}
},
- "color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
- },
- "combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
- "requires": {
- "delayed-stream": "~1.0.0"
- }
- },
- "commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
- },
- "component-emitter": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
- "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
- "dev": true
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
- },
- "config-chain": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
- "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
- "requires": {
- "ini": "^1.3.4",
- "proto-list": "~1.2.1"
- }
- },
- "connect-flash": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz",
- "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA="
- },
- "content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "requires": {
- "safe-buffer": "5.2.1"
- }
- },
- "content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
- },
- "cookie": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
- "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA=="
- },
- "cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
- },
- "cookiejar": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
- "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==",
- "dev": true
- },
- "core-util-is": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
- "dev": true
- },
- "d": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
- "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
- "requires": {
- "es5-ext": "^0.10.50",
- "type": "^1.0.1"
- }
- },
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "requires": {
- "ms": "2.0.0"
- }
- },
- "decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
- },
- "deep-eql": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
- "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
- "requires": {
- "type-detect": "^4.0.0"
- }
- },
- "define-properties": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
- "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
- "requires": {
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- }
- },
- "delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "eslint-config-standard": {
+ "version": "16.0.3",
+ "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz",
+ "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==",
"dev": true
},
- "denque": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
- "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw=="
- },
- "depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
- },
- "destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
- },
- "diff": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
- "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
- },
- "dottie": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz",
- "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg=="
- },
- "editorconfig": {
- "version": "0.15.3",
- "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
- "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==",
+ "eslint-import-resolver-node": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz",
+ "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==",
+ "dev": true,
"requires": {
- "commander": "^2.19.0",
- "lru-cache": "^4.1.5",
- "semver": "^5.6.0",
- "sigmund": "^1.0.1"
+ "debug": "^3.2.7",
+ "is-core-module": "^2.11.0",
+ "resolve": "^1.22.1"
},
"dependencies": {
- "lru-cache": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
- "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
"requires": {
- "pseudomap": "^1.0.2",
- "yallist": "^2.1.2"
+ "ms": "^2.1.1"
}
},
- "yallist": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ "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
}
}
},
- "ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
- },
- "emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
- },
- "encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
- },
- "es-abstract": {
- "version": "1.19.5",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.5.tgz",
- "integrity": "sha512-Aa2G2+Rd3b6kxEUKTF4TaW67czBLyAv3z7VOhYRU50YBx+bbsYZ9xQP4lMNazePuFlybXI0V4MruPos7qUo5fA==",
+ "eslint-module-utils": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
+ "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
+ "dev": true,
"requires": {
- "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"
+ "debug": "^3.2.7"
},
"dependencies": {
- "object.assign": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
- "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
"requires": {
- "call-bind": "^1.0.0",
- "define-properties": "^1.1.3",
- "has-symbols": "^1.0.1",
- "object-keys": "^1.1.1"
+ "ms": "^2.1.1"
}
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
}
}
},
- "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==",
+ "eslint-plugin-es": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz",
+ "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==",
+ "dev": true,
"requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
+ "eslint-utils": "^2.0.0",
+ "regexpp": "^3.0.0"
}
},
- "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==",
+ "eslint-plugin-import": {
+ "version": "2.23.4",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz",
+ "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==",
+ "dev": true,
"requires": {
- "es6-iterator": "^2.0.3",
- "es6-symbol": "^3.1.3",
- "next-tick": "^1.1.0"
+ "array-includes": "^3.1.3",
+ "array.prototype.flat": "^1.2.4",
+ "debug": "^2.6.9",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.4",
+ "eslint-module-utils": "^2.6.1",
+ "find-up": "^2.0.0",
+ "has": "^1.0.3",
+ "is-core-module": "^2.4.0",
+ "minimatch": "^3.0.4",
+ "object.values": "^1.1.3",
+ "pkg-up": "^2.0.0",
+ "read-pkg-up": "^3.0.0",
+ "resolve": "^1.20.0",
+ "tsconfig-paths": "^3.9.0"
+ },
+ "dependencies": {
+ "doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "dev": true
+ }
}
},
- "es6-iterator": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
- "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+ "eslint-plugin-node": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
+ "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==",
+ "dev": true,
"requires": {
- "d": "1",
- "es5-ext": "^0.10.35",
- "es6-symbol": "^3.1.1"
+ "eslint-plugin-es": "^3.0.0",
+ "eslint-utils": "^2.0.0",
+ "ignore": "^5.1.1",
+ "minimatch": "^3.0.4",
+ "resolve": "^1.10.1",
+ "semver": "^6.1.0"
+ },
+ "dependencies": {
+ "ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
}
},
- "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==",
+ "eslint-plugin-promise": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz",
+ "integrity": "sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng==",
+ "dev": true
+ },
+ "eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
"requires": {
- "d": "^1.0.1",
- "ext": "^1.1.2"
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
}
},
- "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==",
+ "eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
"requires": {
- "d": "1",
- "es5-ext": "^0.10.46",
- "es6-iterator": "^2.0.3",
- "es6-symbol": "^3.1.1"
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
}
},
- "escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ "eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true
},
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+ "espree": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+ "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.4.0",
+ "acorn-jsx": "^5.3.1",
+ "eslint-visitor-keys": "^1.3.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true
+ }
+ }
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
+ "esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ }
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ },
+ "dependencies": {
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ }
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -3796,6 +1734,33 @@
"resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz",
"integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8="
},
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
"fill-keys": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz",
@@ -3846,6 +1811,30 @@
"is-buffer": "~2.0.3"
}
},
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true
+ },
+ "for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "requires": {
+ "is-callable": "^1.1.3"
+ }
+ },
"form-data": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
@@ -3893,6 +1882,28 @@
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
+ "function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ }
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+ "dev": true
+ },
+ "functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="
+ },
"generate-function": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
@@ -3912,13 +1923,22 @@
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
},
"get-intrinsic": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
- "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
+ "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
- "has-symbols": "^1.0.1"
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3"
+ }
+ },
+ "get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "requires": {
+ "pump": "^3.0.0"
}
},
"get-symbol-description": {
@@ -3935,12 +1955,64 @@
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
"integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
"requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "requires": {
+ "define-properties": "^1.1.3"
+ }
+ },
+ "gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "requires": {
+ "get-intrinsic": "^1.1.3"
+ }
+ },
+ "got": {
+ "version": "11.8.6",
+ "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
+ "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
+ "requires": {
+ "@sindresorhus/is": "^4.0.0",
+ "@szmarczak/http-timer": "^4.0.5",
+ "@types/cacheable-request": "^6.0.1",
+ "@types/responselike": "^1.0.0",
+ "cacheable-lookup": "^5.0.3",
+ "cacheable-request": "^7.0.2",
+ "decompress-response": "^6.0.0",
+ "http2-wrapper": "^1.0.0-beta.5.2",
+ "lowercase-keys": "^2.0.0",
+ "p-cancelable": "^2.0.0",
+ "responselike": "^2.0.0"
}
},
"graceful-fs": {
@@ -3962,9 +2034,9 @@
}
},
"has-bigints": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
- "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ=="
},
"has-flag": {
"version": "3.0.0",
@@ -3979,6 +2051,11 @@
"get-intrinsic": "^1.1.1"
}
},
+ "has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="
+ },
"has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
@@ -3997,6 +2074,17 @@
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
+ "hosted-git-info": {
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
+ "dev": true
+ },
+ "http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
+ },
"http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@@ -4016,6 +2104,15 @@
}
}
},
+ "http2-wrapper": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
+ "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
+ "requires": {
+ "quick-lru": "^5.1.1",
+ "resolve-alpn": "^1.0.0"
+ }
+ },
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -4024,6 +2121,55 @@
"safer-buffer": ">= 2.1.2 < 3"
}
},
+ "ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true
+ },
+ "imgur": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/imgur/-/imgur-1.0.2.tgz",
+ "integrity": "sha512-bZJkRpa3ReR7lSEzAOjO4PPl9OIDQPuiKoG2aOh36PrTBQCrZL/oTcc6VClyyXEg9O6rEMpsuCloxfhqybpfZA==",
+ "requires": {
+ "commander": "^7.1.0",
+ "form-data": "^4.0.0",
+ "got": "^11.8.1"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
+ },
+ "form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ }
+ }
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true
+ },
"inflection": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.2.tgz",
@@ -4049,11 +2195,11 @@
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"internal-slot": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
- "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
"requires": {
- "get-intrinsic": "^1.1.0",
+ "get-intrinsic": "^1.2.0",
"has": "^1.0.3",
"side-channel": "^1.0.4"
}
@@ -4063,6 +2209,22 @@
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
},
+ "is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
"is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
@@ -4086,14 +2248,14 @@
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
},
"is-callable": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
- "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w=="
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="
},
"is-core-module": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
- "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
+ "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
"requires": {
"has": "^1.0.3"
}
@@ -4106,11 +2268,26 @@
"has-tostringtag": "^1.0.0"
}
},
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
"is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@@ -4173,6 +2350,18 @@
"has-symbols": "^1.0.2"
}
},
+ "is-typed-array": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
+ "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
+ "requires": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
"is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
@@ -4184,8 +2373,7 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
- "dev": true
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"isexe": {
"version": "2.0.0",
@@ -4203,6 +2391,12 @@
"nopt": "^5.0.0"
}
},
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
"js-yaml": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
@@ -4212,6 +2406,38 @@
"esprima": "^4.0.0"
}
},
+ "json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
@@ -4220,11 +2446,84 @@
"graceful-fs": "^4.1.6"
}
},
+ "jsonwebtoken": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+ "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
+ "requires": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^5.6.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ }
+ }
+ },
"just-extend": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz",
"integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg=="
},
+ "jwa": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+ "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "requires": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "jws": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+ "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "requires": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "keyv": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
+ "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==",
+ "requires": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ }
+ },
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
@@ -4244,6 +2543,53 @@
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
"integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
},
+ "lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
+ },
+ "lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
+ },
+ "lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
+ },
+ "lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
+ },
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
+ },
+ "lodash.truncate": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
+ "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
+ "dev": true
+ },
"log-symbols": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
@@ -4265,6 +2611,11 @@
"get-func-name": "^2.0.0"
}
},
+ "lowercase-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="
+ },
"lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -4350,6 +2701,11 @@
"mime-db": "1.52.0"
}
},
+ "mimic-response": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
+ },
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -4440,6 +2796,21 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
+ "multer": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz",
+ "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==",
+ "requires": {
+ "append-field": "^1.0.0",
+ "busboy": "^0.2.11",
+ "concat-stream": "^1.5.2",
+ "mkdirp": "^0.5.4",
+ "object-assign": "^4.1.1",
+ "on-finished": "^2.3.0",
+ "type-is": "^1.6.4",
+ "xtend": "^4.0.0"
+ }
+ },
"mysql2": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-1.7.0.tgz",
@@ -4489,6 +2860,12 @@
}
}
},
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
"negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@@ -4543,10 +2920,32 @@
"abbrev": "1"
}
},
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-url": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
+ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+ },
"object-inspect": {
- "version": "1.12.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
- "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g=="
},
"object-keys": {
"version": "1.1.1",
@@ -4574,6 +2973,17 @@
"es-abstract": "^1.19.1"
}
},
+ "object.values": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
+ "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
"on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@@ -4595,6 +3005,25 @@
"wrappy": "1"
}
},
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "p-cancelable": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
+ "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="
+ },
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
@@ -4616,6 +3045,25 @@
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
},
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -4630,6 +3078,54 @@
"pause": "0.0.1"
}
},
+ "passport-jwt": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.1.tgz",
+ "integrity": "sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==",
+ "requires": {
+ "jsonwebtoken": "^9.0.0",
+ "passport-strategy": "^1.0.0"
+ },
+ "dependencies": {
+ "jsonwebtoken": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz",
+ "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==",
+ "requires": {
+ "jws": "^3.2.2",
+ "lodash": "^4.17.21",
+ "ms": "^2.1.1",
+ "semver": "^7.3.8"
+ }
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "semver": {
+ "version": "7.5.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
+ "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ }
+ }
+ },
"passport-local": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz",
@@ -4653,6 +3149,12 @@
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
"path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
@@ -4663,6 +3165,15 @@
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
"pathval": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
@@ -4678,10 +3189,81 @@
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz",
"integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ=="
},
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "dev": true
+ },
+ "pkg-up": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
+ "integrity": "sha512-fjAPuiws93rm7mPUu21RdBnkeZNrbfCFCwfAhPWY+rR3zG0ubpe5cEReHOw5fIbfmsxEV/g2kSxGTATY3Bpnwg==",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "dev": true
+ }
+ }
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
"dev": true
},
"proto-list": {
@@ -4714,6 +3296,21 @@
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
},
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true
+ },
"qs": {
"version": "6.10.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
@@ -4722,6 +3319,11 @@
"side-channel": "^1.0.4"
}
},
+ "quick-lru": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="
+ },
"random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
@@ -4743,11 +3345,76 @@
"unpipe": "1.0.0"
}
},
+ "read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
+ "dev": true,
+ "requires": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ }
+ },
+ "read-pkg-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
+ "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==",
+ "dev": true,
+ "requires": {
+ "find-up": "^2.0.0",
+ "read-pkg": "^3.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dev": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "dev": true
+ }
+ }
+ },
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
- "dev": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -4761,41 +3428,100 @@
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}
}
},
+ "regexp.prototype.flags": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz",
+ "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "functions-have-names": "^1.2.3"
+ }
+ },
+ "regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true
+ },
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
+ "require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true
+ },
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
},
"resolve": {
- "version": "1.22.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
- "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+ "version": "1.22.2",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
+ "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
"requires": {
- "is-core-module": "^2.8.1",
+ "is-core-module": "^2.11.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
}
},
+ "resolve-alpn": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ },
+ "responselike": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
+ "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
+ "requires": {
+ "lowercase-keys": "^2.0.0"
+ }
+ },
"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=="
},
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
+ "safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ }
+ },
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -4951,8 +3677,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",
@@ -4975,6 +3700,21 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -5026,8 +3766,143 @@
"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=="
+ },
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ }
+ }
+ },
+ "socket.io": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.1.tgz",
+ "integrity": "sha512-W+utHys2w//dhFjy7iQQu9sGd3eokCjGbl2r59tyLqNiJJBdIebn3GAKEXBr3osqHTObJi2die/25bCx2zsaaw==",
+ "requires": {
+ "accepts": "~1.3.4",
+ "base64id": "~2.0.0",
+ "cors": "~2.8.5",
+ "debug": "~4.3.2",
+ "engine.io": "~6.5.0",
+ "socket.io-adapter": "~2.5.2",
+ "socket.io-parser": "~4.2.4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "socket.io-adapter": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz",
+ "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==",
+ "requires": {
+ "ws": "~8.11.0"
+ }
+ },
+ "socket.io-parser": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
+ "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
+ "requires": {
+ "@socket.io/component-emitter": "~3.1.0",
+ "debug": "~4.3.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.13",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz",
+ "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==",
+ "dev": true
},
"sprintf-js": {
"version": "1.0.3",
@@ -5044,22 +3919,10 @@
"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
- }
- }
+ "streamsearch": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
+ "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA=="
},
"string-width": {
"version": "2.1.1",
@@ -5070,22 +3933,49 @@
"strip-ansi": "^4.0.0"
}
},
+ "string.prototype.trim": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
+ "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
"string.prototype.trimend": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
- "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
+ "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
"requires": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
}
},
"string.prototype.trimstart": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
- "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
+ "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
"requires": {
"call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ }
}
},
"strip-ansi": {
@@ -5103,6 +3993,12 @@
}
}
},
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true
+ },
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
@@ -5166,6 +4062,83 @@
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
},
+ "table": {
+ "version": "6.8.1",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz",
+ "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==",
+ "dev": true,
+ "requires": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ }
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
"timers-ext": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
@@ -5185,16 +4158,43 @@
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
"integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg="
},
+ "tsconfig-paths": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
+ "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
+ "dev": true,
+ "requires": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
"type": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
"type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
},
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
+ },
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -5204,6 +4204,21 @@
"mime-types": "~2.1.24"
}
},
+ "typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "requires": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+ },
"uid-safe": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
@@ -5221,13 +4236,13 @@
}
},
"unbox-primitive": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
- "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
"requires": {
- "function-bind": "^1.1.1",
- "has-bigints": "^1.0.1",
- "has-symbols": "^1.0.2",
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
"which-boxed-primitive": "^1.0.2"
}
},
@@ -5241,11 +4256,19 @@
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
- "dev": true
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"utils-merge": {
"version": "1.0.1",
@@ -5257,6 +4280,22 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
+ "v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
"validator": {
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
@@ -5292,6 +4331,19 @@
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
},
+ "which-typed-array": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
+ "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
+ "requires": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0",
+ "is-typed-array": "^1.1.10"
+ }
+ },
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
@@ -5308,6 +4360,12 @@
"@types/node": "*"
}
},
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true
+ },
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
@@ -5348,6 +4406,16 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
+ "ws": {
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
+ "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg=="
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
+ },
"y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
diff --git a/package.json b/package.json
index f6a07e1a29..8140acdc24 100644
--- a/package.json
+++ b/package.json
@@ -6,29 +6,45 @@
"scripts": {
"start": "NODE_ENV=development node app.js",
"dev": "NODE_ENV=development nodemon app.js",
- "test": "mocha test --exit --recursive --timeout 5000"
+ "lint": "eslint \"**/*.js\" --fix",
+ "test": "mocha test --exit --recursive --timeout 5000",
+ "local-test": "NODE_ENV=test mocha test --exit --recursive --timeout 5000",
+ "echo": "echo $NODE_ENV"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt-nodejs": "0.0.3",
+ "bcryptjs": "^2.4.3",
"body-parser": "^1.18.3",
"chai": "^4.2.0",
"connect-flash": "^0.1.1",
+ "cors": "^2.8.5",
+ "dotenv": "^10.0.0",
"express": "^4.16.4",
"express-session": "^1.15.6",
"faker": "^4.1.0",
+ "imgur": "^1.0.2",
+ "jsonwebtoken": "^8.5.1",
"method-override": "^3.0.0",
"mocha": "^6.0.2",
+ "multer": "^1.4.3",
"mysql2": "^1.6.4",
"passport": "^0.4.0",
+ "passport-jwt": "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"
+ "sinon-chai": "^3.3.0",
+ "socket.io": "^4.7.1"
},
"devDependencies": {
+ "eslint": "7.32",
+ "eslint-config-standard": "^16.0.3",
+ "eslint-plugin-import": "^2.23.4",
+ "eslint-plugin-node": "11.1",
+ "eslint-plugin-promise": "^5.1.0",
"proxyquire": "^2.1.3",
"sequelize-test-helpers": "^1.4.2",
"supertest": "^3.3.0"
diff --git a/public/images/placeholder1.png b/public/images/placeholder1.png
new file mode 100644
index 0000000000..c1694db86a
Binary files /dev/null and b/public/images/placeholder1.png differ
diff --git a/routes/index.js b/routes/index.js
new file mode 100644
index 0000000000..7822b9c290
--- /dev/null
+++ b/routes/index.js
@@ -0,0 +1,31 @@
+const router = require('express').Router()
+const admin = require('./modules/admin')
+const users = require('./modules/users')
+const tweets = require('./modules/tweets')
+const followships = require('./modules/followship')
+const { apiErrorHandler } = require('../middleware/error-handler')
+const { authenticated } = require('../middleware/auth')
+const passport = require('passport')
+const userController = require('../controllers/user-controller')
+const adminController = require('../controllers/admin-controller')
+const { isUser, isAdmin, isAuthUser, isAuthAdmin } = require('../middleware/role-check')
+
+// admin
+router.post('/api/admin/login', passport.authenticate('local', { session: false }), isAdmin, adminController.login)
+router.use('/api/admin', authenticated, isAuthAdmin, admin)
+
+// users
+router.post('/api/users', userController.signup)
+router.post('/api/users/login', passport.authenticate('local', { session: false }), isUser, userController.login)
+router.use('/api/users', authenticated, isAuthUser, users)
+
+// tweets
+router.use('/api/tweets', authenticated, isAuthUser, tweets)
+
+// followships
+router.use('/api/followships', authenticated, isAuthUser, followships)
+
+// error handler
+router.use('/', apiErrorHandler)
+
+module.exports = router
diff --git a/routes/modules/admin.js b/routes/modules/admin.js
new file mode 100644
index 0000000000..1ce9ab7f43
--- /dev/null
+++ b/routes/modules/admin.js
@@ -0,0 +1,9 @@
+const router = require('express').Router()
+const adminController = require('../../controllers/admin-controller')
+
+router.delete('/tweets/:id', adminController.deleteTweet)
+router.get('/tweets', adminController.getTweets)
+router.get('/users', adminController.getUsers)
+router.get('/usersdata', adminController.getUsersData)
+
+module.exports = router
diff --git a/routes/modules/followship.js b/routes/modules/followship.js
new file mode 100644
index 0000000000..f229f651e8
--- /dev/null
+++ b/routes/modules/followship.js
@@ -0,0 +1,7 @@
+const router = require('express').Router()
+const followshipController = require('../../controllers/followship-controller')
+
+router.post('/', followshipController.postFollowship) // 追隨使用者
+router.delete('/:followingId', followshipController.deleteFollowship) // 刪除followship
+
+module.exports = router
diff --git a/routes/modules/tweets.js b/routes/modules/tweets.js
new file mode 100644
index 0000000000..82107effbf
--- /dev/null
+++ b/routes/modules/tweets.js
@@ -0,0 +1,13 @@
+const router = require('express').Router()
+const tweetController = require('../../controllers/tweet-controller')
+
+router.post('/:tweetId/replies', tweetController.postReply) // 在推文中新增一條回覆
+router.get('/:tweetId/replies', tweetController.getReplies) // 瀏覽推文下所有回覆
+router.post('/:tweetId/like', tweetController.postLike) // 對堆文like
+router.post('/:tweetId/unlike', tweetController.postUnlike) // 對推文取消like
+
+router.get('/:tweetId', tweetController.getTweet)
+router.get('/', tweetController.getTweets)
+router.post('/', tweetController.postTweet)
+
+module.exports = router
diff --git a/routes/modules/users.js b/routes/modules/users.js
new file mode 100644
index 0000000000..5564028635
--- /dev/null
+++ b/routes/modules/users.js
@@ -0,0 +1,15 @@
+const router = require('express').Router()
+const userController = require('../../controllers/user-controller')
+const { multiUpload } = require('../../middleware/multer')
+
+router.get('/topFollowers', userController.getTopFollower) // 取得follower 前10多的user資料
+router.get('/:id/tweets', userController.getUserTweets) // 取得user發過的tweets
+router.get('/:id/replied_tweets', userController.getUserReplies)// 取得user回覆的tweets
+router.get('/:id/likes', userController.getUserLikes) // 取得user Like過的tweets
+router.get('/:id/followings', userController.getFollowings)// 取得user正在追蹤的使用者
+router.get('/:id/followers', userController.getFollowers)// 取得正在追蹤user的使用者
+router.put('/:id/profile', multiUpload, userController.putUserProfile) // 編輯user profile
+router.put('/:id', userController.putUserSetting) // 編輯user Setting資料
+router.get('/:id', userController.getUserData) // 取得user資料
+
+module.exports = router
diff --git a/seeders/20230606061719-user-seeder.js b/seeders/20230606061719-user-seeder.js
new file mode 100644
index 0000000000..088c247600
--- /dev/null
+++ b/seeders/20230606061719-user-seeder.js
@@ -0,0 +1,48 @@
+const bcrypt = require('bcryptjs')
+const faker = require('faker')
+const numOfUsers = 15
+
+module.exports = {
+ up: async (queryInterface, Sequelize) => {
+ const avatarsIndex = Array.from(Array(numOfUsers).keys())
+
+ await queryInterface.bulkInsert(
+ 'Users',
+ Array.from({ length: numOfUsers }, (_, i) =>
+ i === 0
+ ? {
+ // admin account
+ email: 'root@example.com',
+ account: 'root',
+ password: bcrypt.hashSync('12345678', 10), // 直接使用hashSync同步生成hash
+ role: 'admin',
+ name: 'root',
+ avatar: `https://i.pravatar.cc/300?img=${avatarsIndex[i]}`,
+ introduction: faker.lorem.words(5),
+ cover: `https://picsum.photos/id/${Math.floor(Math.random() * 100)}/640/480`,
+ createdAt: new Date(),
+ updatedAt: new Date()
+ }
+ : {
+ // at least 5 users
+ email: `user${i}@example.com`,
+ account: `user${i}`,
+ password: bcrypt.hashSync('12345678', 10),
+ role: 'user',
+ name: `user${i}`,
+ avatar: `https://i.pravatar.cc/300?img=${avatarsIndex[i]}`,
+ introduction: faker.lorem.words(5),
+ cover: `https://picsum.photos/id/${Math.floor(Math.random() * 100)}/640/480`,
+ createdAt: new Date(),
+ updatedAt: new Date()
+ }
+ ),
+ {}
+ )
+ },
+
+ down: async (queryInterface, Sequelize) => {
+ // 清空資料表中所有資料
+ await queryInterface.bulkDelete('Users', {})
+ }
+}
diff --git a/seeders/20230606074720-add-tweets-seeders.js b/seeders/20230606074720-add-tweets-seeders.js
new file mode 100644
index 0000000000..0386111fd2
--- /dev/null
+++ b/seeders/20230606074720-add-tweets-seeders.js
@@ -0,0 +1,32 @@
+'use strict'
+const faker = require('faker')
+
+module.exports = {
+ up: async (queryInterface, Sequelize) => {
+ // find user id first and exclude admin account
+ const users = await queryInterface.sequelize.query(
+ "SELECT id FROM Users WHERE role <> 'admin'",
+ {
+ type: queryInterface.sequelize.QueryTypes.SELECT
+ }
+ )
+ const tweets = [] // add this variable in to table
+ users.forEach(user => {
+ tweets.push(
+ ...Array.from({ length: 20 }, (_, i) => ({
+ UserId: user.id,
+ description: faker.lorem.paragraph(1).slice(0, 140),
+ createdAt: new Date(),
+ updatedAt: new Date()
+ }))
+ )
+ })
+ await queryInterface.bulkInsert('Tweets',
+ tweets
+ )
+ },
+
+ down: async (queryInterface, Sequelize) => {
+ await queryInterface.bulkDelete('Tweets', {})
+ }
+}
diff --git a/seeders/20230606083101-add-replies-seeders.js b/seeders/20230606083101-add-replies-seeders.js
new file mode 100644
index 0000000000..022a24a87d
--- /dev/null
+++ b/seeders/20230606083101-add-replies-seeders.js
@@ -0,0 +1,32 @@
+'use strict'
+const faker = require('faker')
+module.exports = {
+ up: async (queryInterface, Sequelize) => {
+ const users = await queryInterface.sequelize.query(
+ "SELECT id FROM Users WHERE role <> 'admin'",
+ { type: queryInterface.sequelize.QueryTypes.SELECT }
+ )
+ const tweets = await queryInterface.sequelize.query(
+ 'SELECT id FROM Tweets',
+ { type: queryInterface.sequelize.QueryTypes.SELECT }
+ )
+ const replies = []
+ tweets.forEach(tweet => {
+ replies.push(
+ ...Array.from({ length: 5 }, (_, i) => ({
+ UserId: users[Math.floor(Math.random() * users.length)].id,
+ TweetId: tweet.id,
+ comment: faker.lorem.paragraph(1),
+ createdAt: new Date(),
+ updatedAt: new Date()
+ }))
+ )
+ })
+
+ await queryInterface.bulkInsert('Replies', replies)
+ },
+
+ down: async (queryInterface, Sequelize) => {
+ await queryInterface.bulkDelete('Replies', {})
+ }
+}
diff --git a/seeders/20230606084457-add-likes-seeders.js b/seeders/20230606084457-add-likes-seeders.js
new file mode 100644
index 0000000000..74d430e184
--- /dev/null
+++ b/seeders/20230606084457-add-likes-seeders.js
@@ -0,0 +1,39 @@
+'use strict'
+
+module.exports = {
+ up: async (queryInterface, Sequelize) => {
+ // find user id first and exclude admin account
+ const users = await queryInterface.sequelize.query(
+ "SELECT id FROM Users WHERE role <> 'admin'",
+ { type: queryInterface.sequelize.QueryTypes.SELECT }
+ )
+ // find all tweets id
+ const tweets = await queryInterface.sequelize.query(
+ 'SELECT id FROM Tweets;',
+ { type: queryInterface.sequelize.QueryTypes.SELECT }
+ )
+
+ const likes = []
+ // Each user randomly likes 3 tweets
+ const numOfLikes = 10
+ users.forEach(user => {
+ const unlikeTweets = tweets.map(tweet => tweet.id)
+ for (let i = 0; i < numOfLikes; i++) {
+ const randomIndex = Math.floor(Math.random() * unlikeTweets.length)
+ likes.push({
+ UserId: user.id,
+ TweetId: unlikeTweets[randomIndex],
+ createdAt: new Date(),
+ updatedAt: new Date()
+ })
+ // avoid to like same tweet
+ unlikeTweets.splice(randomIndex, 1)
+ }
+ })
+ await queryInterface.bulkInsert('Likes', likes)
+ },
+
+ down: async (queryInterface, Sequelize) => {
+ await queryInterface.bulkDelete('Likes', {})
+ }
+}
diff --git a/seeders/20230606084513-add-followship-seeders.js b/seeders/20230606084513-add-followship-seeders.js
new file mode 100644
index 0000000000..c286424fe5
--- /dev/null
+++ b/seeders/20230606084513-add-followship-seeders.js
@@ -0,0 +1,36 @@
+'use strict'
+
+module.exports = {
+ up: async (queryInterface, Sequelize) => {
+ // find user id first and exclude admin account
+ const users = await queryInterface.sequelize.query(
+ "SELECT id FROM Users WHERE role <> 'admin'",
+ { type: queryInterface.sequelize.QueryTypes.SELECT }
+ )
+
+ const followships = []
+ // Each user randomly follows 2 users
+ const numOfFollowing = 5
+ users.forEach(user => {
+ // avoid to follow self
+ const excludeSelfUsers = users.filter(u => u.id !== user.id)
+
+ for (let i = 0; i < numOfFollowing; i++) {
+ const randomIndex = Math.floor(Math.random() * excludeSelfUsers.length)
+ followships.push({
+ followerId: user.id,
+ followingId: excludeSelfUsers[randomIndex].id,
+ createdAt: new Date(),
+ updatedAt: new Date()
+ })
+ // avoid to follow same user
+ excludeSelfUsers.splice(randomIndex, 1)
+ }
+ })
+ await queryInterface.bulkInsert('Followships', followships)
+ },
+
+ down: async (queryInterface, Sequelize) => {
+ await queryInterface.bulkDelete('Followships', {})
+ }
+}
diff --git a/seeders/20230709124955-add-room-seed.js b/seeders/20230709124955-add-room-seed.js
new file mode 100644
index 0000000000..26aa6b5178
--- /dev/null
+++ b/seeders/20230709124955-add-room-seed.js
@@ -0,0 +1,44 @@
+'use strict'
+
+module.exports = {
+ up: async (queryInterface, Sequelize) => {
+ // find user id first and exclude admin account
+ const users = await queryInterface.sequelize.query(
+ "SELECT id FROM Users WHERE role <> 'admin'",
+ { type: queryInterface.sequelize.QueryTypes.SELECT }
+ )
+
+ const rooms = [{
+ userOneId: null,
+ userTwoId: null,
+ createdAt: new Date(),
+ updatedAt: new Date()
+ }]
+ users.forEach(user => {
+ const excludeSelfUsers = users.filter(u => u.id !== user.id)
+ for (let i = 0; i < 2; i++) {
+ const randomIndex = Math.floor(Math.random() * excludeSelfUsers.length)
+ const isRoomExist = rooms.some(r =>
+ (r.userOneId === user.id & r.userTwoId === excludeSelfUsers[randomIndex].id) ||
+ (r.userOneId === excludeSelfUsers[randomIndex].id && r.userTwoId === user.id))
+ if (!isRoomExist) {
+ rooms.push({
+ userOneId: user.id,
+ userTwoId: excludeSelfUsers[randomIndex].id,
+ createdAt: new Date(),
+ updatedAt: new Date()
+ })
+ } else {
+ i--
+ }
+ // avoid to follow same user
+ excludeSelfUsers.splice(randomIndex, 1)
+ }
+ })
+ await queryInterface.bulkInsert('Rooms', rooms)
+ },
+
+ down: async (queryInterface, Sequelize) => {
+ await queryInterface.bulkDelete('Rooms', {})
+ }
+}
diff --git a/seeders/20230709130209-add-chat-seed.js b/seeders/20230709130209-add-chat-seed.js
new file mode 100644
index 0000000000..3a413fd391
--- /dev/null
+++ b/seeders/20230709130209-add-chat-seed.js
@@ -0,0 +1,54 @@
+'use strict'
+const faker = require('faker')
+
+module.exports = {
+ up: async (queryInterface, Sequelize) => {
+ // find user id first and exclude admin account
+ const users = await queryInterface.sequelize.query(
+ "SELECT id FROM Users WHERE role <> 'admin'",
+ { type: queryInterface.sequelize.QueryTypes.SELECT }
+ )
+ // find room id and user in room
+ const rooms = await queryInterface.sequelize.query(
+ 'SELECT id, userOneId, userTwoId FROM Rooms',
+ { type: queryInterface.sequelize.QueryTypes.SELECT }
+ )
+ const chats = []
+ for (let i = 0; i < rooms.length; i++) {
+ if (i === 0) {
+ chats.push(...Array.from({ length: 6 }, () => ({
+ message: faker.lorem.words(2),
+ userId: users[Math.floor(Math.random() * users.length)].id,
+ roomId: rooms[0].id,
+ timestamp: new Date(),
+ createdAt: new Date(),
+ updatedAt: new Date()
+ })))
+ } else {
+ for (let j = 0; j < 3; j++) {
+ chats.push({
+ message: faker.lorem.words(2),
+ userId: rooms[i].userOneId,
+ roomId: rooms[i].id,
+ timestamp: new Date(),
+ createdAt: new Date(),
+ updatedAt: new Date()
+ },
+ {
+ message: faker.lorem.words(2),
+ userId: rooms[i].userTwoId,
+ roomId: rooms[i].id,
+ timestamp: new Date(),
+ createdAt: new Date(),
+ updatedAt: new Date()
+ })
+ }
+ }
+ }
+ await queryInterface.bulkInsert('Chats', chats)
+ },
+
+ down: async (queryInterface, Sequelize) => {
+ await queryInterface.bulkDelete('Chats', {})
+ }
+}
diff --git a/socket/helper/index.js b/socket/helper/index.js
new file mode 100644
index 0000000000..8f65af4ea0
--- /dev/null
+++ b/socket/helper/index.js
@@ -0,0 +1,60 @@
+// 用來驗證一些基本問題
+
+const { User, Room } = require('../../models')
+const usersInPublic = require('../modules/userOnline')
+const { Op } = require('sequelize')
+
+const helper = {
+ // user in DB
+ userExistInDB: async (input, typeString) => {
+ if (typeString === 'id') input = Number(input)
+ const whereCondition = { [typeString]: input }
+ // if typeString = id, but input is string, Error of NaN
+
+ const user = await User.findOne({
+ where: whereCondition,
+ attributes: ['id', 'account', 'name', 'avatar']
+ })
+ if (!user) throw new Error('使用者不存在!')
+ return user.toJSON()
+ },
+ // user online
+ findUserIndexInPublic: (input, typeString) => {
+ if (typeString === 'id') input = Number(input)
+ const index = usersInPublic.findIndex(user => user[typeString] === input)
+ return index
+ },
+ findUserInPublic: (input, typeString) => {
+ if (typeString === 'id') input = Number(input)
+ return usersInPublic.find(user => user[typeString] === input)
+ },
+ hasMessage: message => {
+ const m = message.trim()
+ if (m.length === 0) throw new Error('沒有打任何訊息!')
+ return m
+ },
+ emitError: (socket, err) => {
+ console.log(`Server Error: ${err.message}`)
+ socket.emit('server-error', `Error: ${err.message}`)
+ },
+ getAllRooms: async userId => {
+ const rooms = await Room.findAll({
+ where: {
+ [Op.or]: [
+ { userOneId: userId },
+ { userTwoId: userId }
+ ]
+ },
+ attributes: ['id'],
+ raw: true
+ })
+ const roomsArray = rooms.map(room => room.id.toString())
+ return roomsArray
+ },
+ joinAllRooms: (socket, rooms) => {
+ rooms.forEach(roomId => {
+ socket.join(roomId.toString())
+ })
+ }
+}
+module.exports = helper
diff --git a/socket/index.js b/socket/index.js
new file mode 100644
index 0000000000..bc19017238
--- /dev/null
+++ b/socket/index.js
@@ -0,0 +1,26 @@
+const join = require('./modules/join')
+const leave = require('./modules/leave')
+const sendMessage = require('./modules/sendMessage')
+const disconnect = require('./modules/disconnect')
+const record = require('./modules/record')
+const getRoom = require('./modules/getRoom')
+
+module.exports = io => {
+ io.on('connection', socket => {
+ console.log(socket.id)
+
+ // 上線
+ socket.on('client-join', account => join(io, socket, account))
+ // 離線
+ socket.on('client-leave', account => leave(io, socket, account))
+ // 傳送訊息
+ socket.on('client-message', (message, time, roomId) => sendMessage(socket, message, time, roomId))
+ // 歷史訊息
+ socket.on('client-record', room => record(io, socket, room))
+ // 取得我跟對象的roomId
+ socket.on('client-get-room', targetId => getRoom(io, socket, targetId))
+
+ // 使用者斷線
+ socket.on('disconnect', reason => disconnect(io, socket, reason))
+ })
+}
diff --git a/socket/modules/disconnect.js b/socket/modules/disconnect.js
new file mode 100644
index 0000000000..63aa0b63f6
--- /dev/null
+++ b/socket/modules/disconnect.js
@@ -0,0 +1,33 @@
+const usersInPublic = require('./userOnline')
+const { emitError, findUserInPublic, findUserIndexInPublic } = require('../helper')
+
+const timeoutTime = 5000 // 5sec
+
+module.exports = async (io, socket, reason) => {
+ try {
+ // 確認者用者在 上線名單中
+ const user = findUserInPublic(socket.id, 'socketId')
+ console.log('disconnect user:', user)
+ // 找不到使用者代表使用者有正常下線 (使用 client-leave)
+ if (!user) return
+
+ // 找到使用者,代表使用者可能斷線,或是刷新頁面
+ const timeout = setTimeout(() => {
+ // 從上線名單移除使用者 (放在裡面以免期間有其他使用者被刪除搞亂index)
+ const index = findUserIndexInPublic(user.account, 'account')
+ usersInPublic.splice(index, 1)
+ // broadcast 更新的上線名單
+ socket.broadcast.emit('server-update', usersInPublic)
+ // broadcast 斷線訊息
+ socket.broadcast.emit('server-leave', `${user.name} 已經斷線`)
+ console.log('使用者已經被移除(使用者斷線)!')
+ }, timeoutTime)
+
+ // 把這筆 timeout 放入使用者裡面給 join 使用
+ const index = findUserIndexInPublic(user.account, 'account')
+ usersInPublic[index].timeout = timeout
+ console.log(`使用者已被放入timeout裡面(${timeoutTime / 1000}秒開始)`)
+ } catch (err) {
+ emitError(socket, err)
+ }
+}
diff --git a/socket/modules/getRoom.js b/socket/modules/getRoom.js
new file mode 100644
index 0000000000..d562effe8c
--- /dev/null
+++ b/socket/modules/getRoom.js
@@ -0,0 +1,59 @@
+const { emitError, findUserInPublic, userExistInDB, getAllRooms, joinAllRooms } = require('../helper')
+const { Room } = require('../../models')
+const { Op } = require('sequelize')
+
+module.exports = async (io, socket, targetId) => {
+ try {
+ console.log('client get room')
+
+ // get user Id
+ const currentUser = findUserInPublic(socket.id, 'socketId')
+ console.log('currentUser:', currentUser)
+
+ if (!currentUser) throw new Error('you need to use client-join first')
+ const currentUserId = currentUser.id
+
+ // check if both id are the same
+ if (currentUserId.toString() === targetId) throw new Error('both id are the same')
+
+ // check target exist in DB
+ await userExistInDB(targetId, 'id')
+
+ // find room.id
+ let room = await Room.findOne({
+ where: {
+ [Op.or]: [
+ { userOneId: currentUserId, userTwoId: targetId },
+ { userOneId: targetId, userTwoId: currentUserId }
+ ]
+ },
+ attributes: ['id']
+ })
+
+ // 沒有房間就做一個出來
+ if (!room) {
+ room = await Room.create({
+ userOneId: currentUserId,
+ userTwoId: targetId
+ })
+ }
+ // 傳遞房間給使用者
+ socket.emit('server-get-room', room.id.toString())
+
+ // 把使用者加入房間
+ const userRooms = await getAllRooms(currentUserId)
+ joinAllRooms(socket, userRooms)
+
+ // 檢查目標是否在線上
+ const targetUser = findUserInPublic(targetId, 'id')
+ if (!targetUser) return
+
+ // 在線上就找到目標socket,找出所屬房間,加入房間,更新資訊
+ const targetSocket = io.sockets.sockets.get(targetUser.socketId)
+ const targetRooms = await getAllRooms(targetId)
+ joinAllRooms(targetSocket, targetRooms)
+ targetUser.rooms = targetRooms
+ } catch (err) {
+ emitError(socket, err)
+ }
+}
diff --git a/socket/modules/join.js b/socket/modules/join.js
new file mode 100644
index 0000000000..1e5720ef8a
--- /dev/null
+++ b/socket/modules/join.js
@@ -0,0 +1,60 @@
+const usersInPublic = require('./userOnline')
+const {
+ userExistInDB,
+ emitError,
+ findUserInPublic,
+ getAllRooms,
+ joinAllRooms
+} = require('../helper')
+
+module.exports = async (io, socket, account) => {
+ try {
+ // 檢查 使用者是否存在上線名單中
+ let userOnList = findUserInPublic(account, 'account')
+
+ // 恢復連線
+ if (userOnList?.timeout) {
+ // 使用者 reconnect
+ console.log('使用者已經恢復連線 取消timeout')
+ clearTimeout(userOnList.timeout)
+ // 更新使用者資訊
+ userOnList.socketId = socket.id
+ // userOnList.rooms = await getAllRooms(userOnList.id)
+ // userOnList.socket = socket
+
+ delete userOnList.timeout
+ }
+
+ // 新上線
+ if (!userOnList) {
+ // 使用者上線
+ console.log('使用者上線')
+ const user = await userExistInDB(account, 'account')
+ // 更新使用者資訊
+ user.socketId = socket.id
+ user.rooms = await getAllRooms(user.id)
+
+ // cause error
+ // user.socketObject = socket
+
+ // 給全部使用者 更新的上線名單
+ usersInPublic.push(user)
+ // 更新 userOnList
+ userOnList = findUserInPublic(account, 'account')
+ // 傳遞名單
+ io.emit('server-update', usersInPublic)
+ // broadcast 上線訊息
+ socket.broadcast.emit('server-join', `${user.name} 上線`)
+ }
+
+ // 把使用者加入擁有的rooms中
+ // 重複的房間會自動忽略
+ const rooms = await getAllRooms(userOnList.id)
+ joinAllRooms(socket, rooms) // join rooms
+
+ console.log('已經把使用者join rooms')
+ console.log('socket.rooms:', socket.rooms)
+ } catch (err) {
+ emitError(socket, err)
+ }
+}
diff --git a/socket/modules/leave.js b/socket/modules/leave.js
new file mode 100644
index 0000000000..4dc9cd0bf1
--- /dev/null
+++ b/socket/modules/leave.js
@@ -0,0 +1,25 @@
+const usersInPublic = require('./userOnline')
+const { userExistInDB, findUserInPublic, findUserIndexInPublic, emitError } = require('../helper')
+
+module.exports = async (io, socket, userAccount) => {
+ try {
+ // 檢查 使用者存在
+ const user = await userExistInDB(userAccount, 'account')
+
+ // 檢查 使用者在不在上線名單上 (暫時傳錯誤給postman)
+ if (!findUserInPublic(user.account, 'account')) throw new Error('使用者已經不在上線名單上!(已下線)')
+
+ // 從上線名單移除使用者
+ usersInPublic.splice(findUserIndexInPublic(user.account, 'account'), 1)
+
+ // 給全部使用者 更新的上線名單
+ socket.broadcast.emit('server-update', usersInPublic)
+ // broadcast 下線訊息
+ socket.broadcast.emit('server-leave', `${user.name} 下線`)
+ return
+ } catch (err) {
+ // 因為使用者已經不在線上,有沒有要處理在考慮
+ // 傳給 postman
+ emitError(socket, err)
+ }
+}
diff --git a/socket/modules/record.js b/socket/modules/record.js
new file mode 100644
index 0000000000..4e931c48d3
--- /dev/null
+++ b/socket/modules/record.js
@@ -0,0 +1,30 @@
+const { emitError } = require('../helper')
+const { Chat, User, Room } = require('../../models')
+
+module.exports = async (io, socket, roomId) => {
+ try {
+ // 如未傳入值,預設為public room
+ if (!roomId) {
+ const room = await Room.findOne({ attributes: ['id'], raw: true })
+ roomId = room.id
+ } else {
+ const room = await Room.findOne({ where: { id: roomId } })
+ if (!room) throw new Error('此聊天室不存在!')
+ }
+ // 訊息由舊到新排序
+ let records = await Chat.findAll({
+ where: { roomId },
+ include: [{ model: User, attributes: ['id', 'name', 'account', 'avatar'] }],
+ nest: true,
+ order: [['timestamp', 'ASC']],
+ attributes: ['message', 'roomId', 'timestamp'],
+ raw: true
+ })
+ records = records.length ? records : '尚未聊天過,開始發送訊息吧!'
+
+ // 回傳歷史訊息
+ io.emit('server-record', records)
+ } catch (err) {
+ emitError(socket, err)
+ }
+}
diff --git a/socket/modules/sendMessage.js b/socket/modules/sendMessage.js
new file mode 100644
index 0000000000..97734505bd
--- /dev/null
+++ b/socket/modules/sendMessage.js
@@ -0,0 +1,54 @@
+const { userExistInDB, hasMessage, findUserInPublic, emitError } = require('../helper')
+const { Chat, Room } = require('../../models')
+
+// 公開訊息與私人訊息之後會使用 room 參數判斷
+module.exports = async (socket, message, timestamp, roomId) => {
+ try {
+ // 避免資料庫跳號問題,先找出public room id
+ const publicRoom = await Room.findOne({ attributes: ['id'], raw: true })
+ // default
+ const room = roomId ?? publicRoom.id
+ const time = timestamp ?? new Date()
+
+ // 檢查 聊天室存在
+ const isRoom = await Room.findOne({ where: { id: room } })
+ if (!isRoom) throw new Error('此聊天室不存在!')
+
+ // 檢查 使用者存在
+ const currentUser = findUserInPublic(socket.id, 'socketId')
+
+ if (!currentUser) throw new Error('You need to client-join first')
+ const userId = currentUser.id
+ const user = await userExistInDB(userId, 'id')
+
+ // 檢查有沒有訊息 (同時用trim)
+ const trimmedMessage = hasMessage(message)
+
+ // 回傳資訊
+ const msgPackage = {
+ user,
+ message: trimmedMessage,
+ timestamp: time,
+ room
+ }
+ // 傳遞
+ if (room.toString() === publicRoom.id.toString()) {
+ // 公開訊息
+ console.log('傳送公開訊息')
+ socket.broadcast.emit('server-message', msgPackage)
+ } else {
+ // 一對一訊息
+ console.log('傳送私人訊息')
+ socket.to(room).emit('server-message', msgPackage)
+ }
+ // 儲存訊息至DB
+ await Chat.create({
+ message: trimmedMessage,
+ userId: user.id,
+ roomId: room,
+ timestamp: time
+ })
+ } catch (err) {
+ emitError(socket, err)
+ }
+}
diff --git a/socket/modules/userOnline.js b/socket/modules/userOnline.js
new file mode 100644
index 0000000000..2323e3779d
--- /dev/null
+++ b/socket/modules/userOnline.js
@@ -0,0 +1,3 @@
+// 公開聊天室 上線名單
+const userInPublic = []
+module.exports = userInPublic
diff --git a/test/models/Followship.spec.js b/test/models/Followship.spec.js
index 893356fc55..f9c89b9282 100644
--- a/test/models/Followship.spec.js
+++ b/test/models/Followship.spec.js
@@ -1,7 +1,7 @@
-const chai = require('chai');
-const sinon = require('sinon');
-const proxyquire = require('proxyquire');
-chai.use(require('sinon-chai'));
+const chai = require('chai')
+const sinon = require('sinon')
+const proxyquire = require('proxyquire')
+chai.use(require('sinon-chai'))
const { expect } = require('chai')
const {
@@ -39,5 +39,4 @@ describe('# Followship Model', () => {
}
)
})
-
})
diff --git a/test/models/Like.spec.js b/test/models/Like.spec.js
index 2d4f3ef3ce..ac7790fb49 100644
--- a/test/models/Like.spec.js
+++ b/test/models/Like.spec.js
@@ -1,7 +1,7 @@
-const chai = require('chai');
-const sinon = require('sinon');
-const proxyquire = require('proxyquire');
-chai.use(require('sinon-chai'));
+const chai = require('chai')
+const sinon = require('sinon')
+const proxyquire = require('proxyquire')
+chai.use(require('sinon-chai'))
const { expect } = require('chai')
const {
@@ -52,12 +52,12 @@ describe('# Like Model', () => {
Like.associate({ Tweet })
})
- it('should belong to user', (done) => {
+ it('should belong to user', done => {
// 檢查是否有呼叫 belongsTo(User)
expect(Like.belongsTo).to.have.been.calledWith(User)
done()
})
- it('should belong to tweet', (done) => {
+ it('should belong to tweet', done => {
// 檢查是否有呼叫 belongsTo(Tweet)
expect(Like.belongsTo).to.have.been.calledWith(Tweet)
done()
@@ -66,41 +66,39 @@ describe('# Like Model', () => {
// 檢查 model 的新增、修改、刪除、更新
context('action', () => {
-
let data = null
// 檢查 db.Like 是否真的可以新增一筆資料
- it('create', (done) => {
- db.Like.create({}).then((like) => {
+ it('create', done => {
+ db.Like.create({}).then(like => {
data = like
done()
})
})
// 檢查 db.Like 是否真的可以讀取一筆資料
- it('read', (done) => {
- db.Like.findByPk(data.id).then((like) => {
- expect(data.id).to.be.equal(like.id)
- done()
- })
+ it('read', done => {
+ db.Like.findByPk(data.id).then(like => {
+ expect(data.id).to.be.equal(like.id)
+ done()
+ })
})
// 檢查 db.Like 是否真的可以更新一筆資料
- it('update', (done) => {
- db.Like.update({}, { where: { id: data.id }}).then(() => {
- db.Like.findByPk(data.id).then((like) => {
- expect(data.updatedAt).to.be.not.equal(like.updatedAt)
+ it('update', done => {
+ db.Like.update({}, { where: { id: data.id } }).then(() => {
+ db.Like.findByPk(data.id).then(like => {
+ expect(data.updatedAt).to.be.not.equal(like.updatedAt)
done()
})
})
})
- // 檢查 db.Like 是否真的可以刪除一筆資料
- it('delete', (done) => {
- db.Like.destroy({ where: { id: data.id }}).then(() => {
- db.Like.findByPk(data.id).then((like) => {
- expect(like).to.be.equal(null)
+ // 檢查 db.Like 是否真的可以刪除一筆資料
+ it('delete', done => {
+ db.Like.destroy({ where: { id: data.id } }).then(() => {
+ db.Like.findByPk(data.id).then(like => {
+ expect(like).to.be.equal(null)
done()
})
})
})
})
-
})
diff --git a/test/models/Reply.spec.js b/test/models/Reply.spec.js
index 33c1ba0443..f85aa0fc9e 100644
--- a/test/models/Reply.spec.js
+++ b/test/models/Reply.spec.js
@@ -1,7 +1,7 @@
-const chai = require('chai');
-const sinon = require('sinon');
-const proxyquire = require('proxyquire');
-chai.use(require('sinon-chai'));
+const chai = require('chai')
+const sinon = require('sinon')
+const proxyquire = require('proxyquire')
+chai.use(require('sinon-chai'))
const { expect } = require('chai')
const {
@@ -37,13 +37,13 @@ describe('# Reply Model', () => {
it('called Reply.init with the correct parameters', () => {
expect(Reply.init).to.have.been.calledWithMatch(
{
- comment: DataTypes.TEXT,
- },
+ comment: DataTypes.TEXT
+ }
)
})
})
- // 檢查 reply 的關聯是否正確
+ // 檢查 reply 的關聯是否正確
context('associations', () => {
const User = 'User'
const Tweet = 'Tweet'
@@ -53,12 +53,12 @@ describe('# Reply Model', () => {
Reply.associate({ Tweet })
})
- it('should belong to user', (done) => {
+ it('should belong to user', done => {
// 檢查是否有呼叫 belongsTo(User)
expect(Reply.belongsTo).to.have.been.calledWith(User)
done()
})
- it('should belong to tweet', (done) => {
+ it('should belong to tweet', done => {
// 檢查是否有呼叫 belongsTo(Tweet)
expect(Reply.belongsTo).to.have.been.calledWith(Tweet)
done()
@@ -66,40 +66,38 @@ describe('# Reply Model', () => {
})
// 檢查 model 的新增、修改、刪除、更新
context('action', () => {
-
let data = null
// 檢查 db.Reply 是否真的可以新增一筆資料
- it('create', (done) => {
- db.Reply.create({}).then((reply) => {
+ it('create', done => {
+ db.Reply.create({}).then(reply => {
data = reply
done()
})
})
// 檢查 db.Reply 是否真的可以讀取一筆資料
- it('read', (done) => {
- db.Reply.findByPk(data.id).then((reply) => {
+ it('read', done => {
+ db.Reply.findByPk(data.id).then(reply => {
expect(data.id).to.be.equal(reply.id)
- done()
- })
+ done()
+ })
})
// 檢查 db.Reply 是否真的可以更新一筆資料
- it('update', (done) => {
- db.Reply.update({}, { where: { id: data.id }}).then(() => {
- db.Reply.findByPk(data.id).then((reply) => {
- expect(data.updatedAt).to.be.not.equal(reply.updatedAt)
+ it('update', done => {
+ db.Reply.update({}, { where: { id: data.id } }).then(() => {
+ db.Reply.findByPk(data.id).then(reply => {
+ expect(data.updatedAt).to.be.not.equal(reply.updatedAt)
done()
})
})
})
// 檢查 db.Reply 是否真的可以刪除一筆資料
- it('delete', (done) => {
- db.Reply.destroy({ where: { id: data.id }}).then(() => {
- db.Reply.findByPk(data.id).then((reply) => {
- expect(reply).to.be.equal(null)
+ it('delete', done => {
+ db.Reply.destroy({ where: { id: data.id } }).then(() => {
+ db.Reply.findByPk(data.id).then(reply => {
+ expect(reply).to.be.equal(null)
done()
})
})
})
})
-
})
diff --git a/test/models/Tweet.spec.js b/test/models/Tweet.spec.js
index 5335b84bdd..fbec60f20f 100644
--- a/test/models/Tweet.spec.js
+++ b/test/models/Tweet.spec.js
@@ -1,7 +1,7 @@
-const chai = require('chai');
-const sinon = require('sinon');
-const proxyquire = require('proxyquire');
-chai.use(require('sinon-chai'));
+const chai = require('chai')
+const sinon = require('sinon')
+const proxyquire = require('proxyquire')
+chai.use(require('sinon-chai'))
const { expect } = require('chai')
const {
@@ -37,8 +37,8 @@ describe('# Tweet Model', () => {
it('called Tweet.init with the correct parameters', () => {
expect(Tweet.init).to.have.been.calledWithMatch(
{
- description: DataTypes.TEXT,
- },
+ description: DataTypes.TEXT
+ }
)
})
})
@@ -55,17 +55,17 @@ describe('# Tweet Model', () => {
Tweet.associate({ User })
})
- it('should have many replies', (done) => {
+ it('should have many replies', done => {
// 檢查是否有呼叫 hasMany(Reply)
expect(Tweet.hasMany).to.have.been.calledWith(Reply)
done()
})
- it('should have many likes', (done) => {
+ it('should have many likes', done => {
// 檢查是否有呼叫 hasMany(Like)
expect(Tweet.hasMany).to.have.been.calledWith(Like)
done()
})
- it('should belong to user', (done) => {
+ it('should belong to user', done => {
// 檢查是否有呼叫 belongsTo(User)
expect(Tweet.belongsTo).to.have.been.calledWith(User)
done()
@@ -74,40 +74,38 @@ describe('# Tweet Model', () => {
// // 檢查 model 的新增、修改、刪除、更新
context('action', () => {
-
let data = null
// 檢查 db.Tweet 是否真的可以新增一筆資料
- it('create', (done) => {
- db.Tweet.create({UserId: 1, description: 'hi'}).then((tweet) => {
+ it('create', done => {
+ db.Tweet.create({ UserId: 1, description: 'hi' }).then(tweet => {
data = tweet
done()
})
})
// 檢查 db.Tweet 是否真的可以讀取一筆資料
- it('read', (done) => {
- db.Tweet.findByPk(data.id).then((tweet) => {
+ it('read', done => {
+ db.Tweet.findByPk(data.id).then(tweet => {
expect(data.id).to.be.equal(tweet.id)
- done()
- })
+ done()
+ })
})
// 檢查 db.Tweet 是否真的可以更新一筆資料
- it('update', (done) => {
- db.Tweet.update({}, { where: { id: data.id }}).then(() => {
- db.Tweet.findByPk(data.id).then((tweet) => {
- expect(data.updatedAt).to.be.not.equal(tweet.updatedAt)
+ it('update', done => {
+ db.Tweet.update({}, { where: { id: data.id } }).then(() => {
+ db.Tweet.findByPk(data.id).then(tweet => {
+ expect(data.updatedAt).to.be.not.equal(tweet.updatedAt)
done()
})
})
})
// 檢查 db.Tweet 是否真的可以刪除一筆資料
- it('delete', (done) => {
- db.Tweet.destroy({ where: { id: data.id }}).then(() => {
- db.Tweet.findByPk(data.id).then((tweet) => {
- expect(tweet).to.be.equal(null)
+ it('delete', done => {
+ db.Tweet.destroy({ where: { id: data.id } }).then(() => {
+ db.Tweet.findByPk(data.id).then(tweet => {
+ expect(tweet).to.be.equal(null)
done()
})
})
})
})
-
})
diff --git a/test/models/User.spec.js b/test/models/User.spec.js
index 0bb4c2dad7..a6a4aa12ec 100644
--- a/test/models/User.spec.js
+++ b/test/models/User.spec.js
@@ -1,6 +1,6 @@
const chai = require('chai')
const sinon = require('sinon')
-const proxyquire = require('proxyquire');
+const proxyquire = require('proxyquire')
chai.use(require('sinon-chai'))
const { expect } = require('chai')
@@ -37,7 +37,7 @@ describe('# User Model', () => {
it('called User.init with the correct parameters', () => {
expect(User.init).to.have.been.calledWithMatch(
{
- name: DataTypes.STRING,
+ name: DataTypes.STRING
}
)
})
@@ -56,22 +56,22 @@ describe('# User Model', () => {
User.associate({ User })
})
- it('should have many replies', (done) => {
+ it('should have many replies', done => {
// 檢查是否有呼叫 hasMany(Reply)
expect(User.hasMany).to.have.been.calledWith(Reply)
done()
})
- it('should have many tweets', (done) => {
+ it('should have many tweets', done => {
// 檢查是否有呼叫 hasMany(Tweet)
expect(User.hasMany).to.have.been.calledWith(Tweet)
done()
})
- it('should have many likes', (done) => {
+ it('should have many likes', done => {
// 檢查是否有呼叫 hasMany(Like)
expect(User.hasMany).to.have.been.calledWith(Like)
done()
})
- it('should have many Users', (done) => {
+ it('should have many Users', done => {
// 檢查是否有呼叫 belongsToMany(User)
expect(User.belongsToMany).to.have.been.calledWith(User)
done()
@@ -82,32 +82,32 @@ describe('# User Model', () => {
context('action', () => {
let data = null
// 檢查 db.User 是否真的可以新增一筆資料
- it('create', (done) => {
- db.User.create({}).then((user) => {
+ it('create', done => {
+ db.User.create({}).then(user => {
data = user
done()
})
})
// 檢查 db.User 是否真的可以讀取一筆資料
- it('read', (done) => {
- db.User.findByPk(data.id).then((user) => {
+ it('read', done => {
+ db.User.findByPk(data.id).then(user => {
expect(data.id).to.be.equal(user.id)
done()
})
})
// 檢查 db.User 是否真的可以更新一筆資料
- it('update', (done) => {
+ it('update', done => {
db.User.update({}, { where: { id: data.id } }).then(() => {
- db.User.findByPk(data.id).then((user) => {
+ db.User.findByPk(data.id).then(user => {
expect(data.updatedAt).to.be.not.equal(user.updatedAt)
done()
})
})
})
// 檢查 db.User 是否真的可以刪除一筆資料
- it('delete', (done) => {
+ it('delete', done => {
db.User.destroy({ where: { id: data.id } }).then(() => {
- db.User.findByPk(data.id).then((user) => {
+ db.User.findByPk(data.id).then(user => {
expect(user).to.be.equal(null)
done()
})
diff --git a/test/requests/admin.spec.js b/test/requests/admin.spec.js
index a8006197f7..2894c3b483 100644
--- a/test/requests/admin.spec.js
+++ b/test/requests/admin.spec.js
@@ -2,119 +2,113 @@ const chai = require('chai')
const request = require('supertest')
const sinon = require('sinon')
const app = require('../../app')
-const helpers = require('../../_helpers');
-const should = chai.should();
-const expect = chai.expect;
+const helpers = require('../../_helpers')
+const should = chai.should()
+const expect = chai.expect
const db = require('../../models')
const passport = require('../../config/passport')
// admin 相關功能測試
// 1. 管理者可以看見站內所有的使用者
-// 2. 管理者可以刪除使用者的推文
+// 2. 管理者可以刪除使用者的推文
describe('# admin requests', () => {
-
context('# GET ', () => {
-
describe(' /api/admin/users', () => {
- before(async() => {
+ before(async () => {
// 清除 User table 的測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => { }
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'admin'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'admin' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
})
// GET /admin/users - 看見站內所有的使用者
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.get('/api/admin/users')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) {
+ console.log('the error:', err)
+ return done(err)
+ }
// 檢查回傳資料是否是陣列類型
- expect(res.body).to.be.an('array');
+ expect(res.body).to.be.an('array')
// 檢查回傳資料是否有 3 筆使用者資料
- res.body.length.should.equal(3);
- return done();
+ res.body.length.should.equal(3)
+ return done()
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
+ })
+ })
context('# DELETE ', () => {
-
describe(' /api/admin/tweets/:id', () => {
- before(async() => {
+ before(async () => {
// 清除 User, Tweet table 的測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => { }
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'admin'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'admin' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
- await db.Tweet.create({UserId: 1, description: 'User1 的 description'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1', role: 'admin' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
+ await db.Tweet.create({ UserId: 1, description: 'User1 的 description' })
})
// DELETE /admin/tweets/:id - 刪除使用者的推文
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.delete('/api/admin/tweets/1')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查是否 Tweet table 中的資料是空的,表示有刪除成功
db.Tweet.findByPk(1).then(tweet => {
expect(tweet).to.be.null
- return done();
+ return done()
})
-
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
-
-});
+ })
+ })
+})
diff --git a/test/requests/followship.spec.js b/test/requests/followship.spec.js
index 45c90131bb..a96fc3122d 100644
--- a/test/requests/followship.spec.js
+++ b/test/requests/followship.spec.js
@@ -2,9 +2,9 @@ const chai = require('chai')
const request = require('supertest')
const sinon = require('sinon')
const app = require('../../app')
-const helpers = require('../../_helpers');
+const helpers = require('../../_helpers')
const should = chai.should()
-const expect = chai.expect;
+const expect = chai.expect
const db = require('../../models')
const passport = require('../../config/passport')
@@ -12,112 +12,104 @@ const passport = require('../../config/passport')
// 1. 可以追蹤使用者
// 2. 可以刪除追蹤使用者
describe('# followship requests', () => {
-
context('# POST ', () => {
-
describe(' /api/followships', () => {
- before(async() => {
+ before(async () => {
// 清除 User, Followship table 的測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Followship.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Followship.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
})
// 新增 POST /followships
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.post('/api/followships')
.send('id=2')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查 Followship 資料裡,是否有 followerId=1, followingId = 2 的資料
db.Followship.findByPk(1).then(followship => {
- followship.followerId.should.equal(1);
- followship.followingId.should.equal(2);
- return done();
+ followship.followerId.should.equal(1)
+ followship.followingId.should.equal(2)
+ return done()
})
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Followship.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Followship.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
+ })
+ })
context('# DELETE ', () => {
-
describe(' /api/followships/:followingId', () => {
- before(async() => {
+ before(async () => {
// 清除 User table 的測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Followship.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Followship.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
- await db.Followship.create({followerId: 1, followingId: 2})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
+ await db.Followship.create({ followerId: 1, followingId: 2 })
})
// 刪除 DETELE /followships/:followingId
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.delete('/api/followships/2')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查 Followship 的資料是否已空,表示已被刪除
db.Followship.findByPk(1).then(followship => {
expect(followship).to.be.null
- return done();
+ return done()
})
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Followship.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Followship.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
-
-});
+ })
+ })
+})
diff --git a/test/requests/like.spec.js b/test/requests/like.spec.js
index 3f3b957c8e..1864b99563 100644
--- a/test/requests/like.spec.js
+++ b/test/requests/like.spec.js
@@ -2,120 +2,114 @@ const chai = require('chai')
const request = require('supertest')
const sinon = require('sinon')
const app = require('../../app')
-const helpers = require('../../_helpers');
-const should = chai.should();
-const expect = chai.expect;
+const helpers = require('../../_helpers')
+const should = chai.should()
+const expect = chai.expect
const db = require('../../models')
const passport = require('../../config/passport')
describe('# like requests', () => {
-
context('# POST ', () => {
-
describe(' /api/tweets/:id/like', () => {
- before(async() => {
+ before(async () => {
// 清除 User, Tweet, Like table 的測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Like.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Like.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
- await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet1'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
+ await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet1' })
})
// POST /tweets/:id/like 喜歡一則推文
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.post('/api/tweets/1/like')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查 Like 資料裡,是否有 UserId=1, TweetId =1 的資料
db.Like.findByPk(1).then(like => {
- like.UserId.should.equal(1);
- like.TweetId.should.equal(1);
- return done();
+ like.UserId.should.equal(1)
+ like.TweetId.should.equal(1)
+ return done()
})
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Like.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Like.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
+ })
describe(' /api/tweets/:id/unlike', () => {
- before(async() => {
+ before(async () => {
// 清除 User, Tweet, Like table 的測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Like.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Like.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
- await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet1'})
- await db.Like.create({UserId: 1, TweetId: 1})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
+ await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet1' })
+ await db.Like.create({ UserId: 1, TweetId: 1 })
})
// POST /tweets/:id/unlike 取消喜歡
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.post('/api/tweets/1/unlike')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查是否 Like table 中的資料是空的,表示有刪除成功
db.Like.findByPk(1).then(like => {
expect(like).to.be.null
- return done();
+ return done()
})
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Like.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Like.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
-
-});
+ })
+ })
+})
diff --git a/test/requests/reply.spec.js b/test/requests/reply.spec.js
index c355eb7eee..d221e9099b 100644
--- a/test/requests/reply.spec.js
+++ b/test/requests/reply.spec.js
@@ -2,124 +2,116 @@ const chai = require('chai')
const request = require('supertest')
const sinon = require('sinon')
const app = require('../../app')
-const helpers = require('../../_helpers');
-const should = chai.should();
-const expect = chai.expect;
+const helpers = require('../../_helpers')
+const should = chai.should()
+const expect = chai.expect
const db = require('../../models')
const passport = require('../../config/passport')
describe('# reply requests', () => {
-
context('# POST ', () => {
-
describe(' /api/tweets/:tweet_id/replies', () => {
- before(async() => {
+ before(async () => {
// 清除 User, Tweet, Reply table 的測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Reply.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Reply.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
- await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet1'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
+ await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet1' })
})
// 新增回覆 POST /tweets/:tweet_id/replies
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.post('/api/tweets/1/replies')
.send('comment=comment')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查是否有成功新增留言
db.Reply.findByPk(1).then(reply => {
- reply.comment.should.equal('comment');
- reply.UserId.should.equal(1);
- reply.TweetId.should.equal(1);
- return done();
+ reply.comment.should.equal('comment')
+ reply.UserId.should.equal(1)
+ reply.TweetId.should.equal(1)
+ return done()
})
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Reply.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Reply.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
+ })
+ })
context('# GET ', () => {
-
describe('GET /api/tweets/:tweet_id/replies', () => {
- before(async() => {
+ before(async () => {
// 清除 User table 的測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Reply.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Reply.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'})
- await db.Reply.create({UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' })
+ await db.Reply.create({ UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment' })
})
// 瀏覽 GET /tweets/:tweet_id/replies
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.get('/api/tweets/1/replies')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查是否有成功取得留言
- expect(res.body).to.be.an('array');
- res.body[0].comment.should.equal('Tweet1 的 comment');
- return done();
+ expect(res.body).to.be.an('array')
+ res.body[0].comment.should.equal('Tweet1 的 comment')
+ return done()
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Reply.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Reply.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
-
-});
+ })
+ })
+})
diff --git a/test/requests/tweet.spec.js b/test/requests/tweet.spec.js
index 1976d7d5b9..bf03fc8bbf 100644
--- a/test/requests/tweet.spec.js
+++ b/test/requests/tweet.spec.js
@@ -2,130 +2,122 @@ const chai = require('chai')
const request = require('supertest')
const sinon = require('sinon')
const app = require('../../app')
-const helpers = require('../../_helpers');
-const should = chai.should();
-const expect = chai.expect;
+const helpers = require('../../_helpers')
+const should = chai.should()
+const expect = chai.expect
const db = require('../../models')
const passport = require('../../config/passport')
describe('# tweet requests', () => {
-
context('# POST ', () => {
-
describe('POST /api/tweets', () => {
- before(async() => {
+ before(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
})
// 新增推文 - POST /tweets
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.post('/api/tweets')
.send('description=description')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查是否有回傳正確資料
db.Tweet.findByPk(1).then(tweet => {
- tweet.description.should.equal('description');
- tweet.UserId.should.equal(1);
- return done();
+ tweet.description.should.equal('description')
+ tweet.UserId.should.equal(1)
+ return done()
})
})
- });
+ })
after(async () => {
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
+ })
+ })
context('# GET ', () => {
-
describe('GET /api/tweets', () => {
- before(async() => {
+ before(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'})
- await db.Reply.create({UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' })
+ await db.Reply.create({ UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment' })
})
// GET /tweets - 所有推文,包括推文作者
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.get('/api/tweets')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
- expect(res.body).to.be.an('array');
+ .end(function (err, res) {
+ if (err) return done(err)
+ expect(res.body).to.be.an('array')
// 檢查是否回傳資料有 User1 的 Tweet1
- res.body[0].description.should.equal('User1 的 Tweet1');
- return done();
+ res.body[0].description.should.equal('User1 的 Tweet1')
+ return done()
})
- });
+ })
// GET /tweets/:tweet_id - 一筆推文
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.get('/api/tweets/1')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
- expect(res.body).to.be.an('object');
- // 檢查是否回傳資料有 User1 的 Tweet1
- res.body.description.should.equal('User1 的 Tweet1');
- return done();
+ .end(function (err, res) {
+ if (err) return done(err)
+ expect(res.body).to.be.an('object')
+ // 檢查是否回傳資料有 User1 的 Tweet1
+ res.body.description.should.equal('User1 的 Tweet1')
+ return done()
})
- });
+ })
after(async () => {
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
-
-});
+ })
+ })
+})
diff --git a/test/requests/user.spec.js b/test/requests/user.spec.js
index e19d5e4229..bc27fc0380 100644
--- a/test/requests/user.spec.js
+++ b/test/requests/user.spec.js
@@ -2,413 +2,391 @@ const chai = require('chai')
const request = require('supertest')
const sinon = require('sinon')
const app = require('../../app')
-const helpers = require('../../_helpers');
+const helpers = require('../../_helpers')
const should = chai.should()
-const expect = chai.expect;
+const expect = chai.expect
const db = require('../../models')
const passport = require('../../config/passport')
describe('# user requests', () => {
-
context('# POST ', () => {
-
describe('POST /api/users', () => {
- before(async() => {
+ before(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
// 註冊自己的帳號 POST /users
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.post('/api/users')
.send('account=User1&name=User1&email=User1@example.com&password=User1&checkPassword=User1')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查是否有成功新增資料到資料庫裡
db.User.findByPk(1).then(user => {
- user.account.should.equal('User1');
- user.email.should.equal('User1@example.com');
- return done();
+ user.account.should.equal('User1')
+ user.email.should.equal('User1@example.com')
+ return done()
})
})
- });
+ })
after(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
-
+ })
+ })
context('# GET ', () => {
-
describe('GET /users/:id', () => {
- before(async() => {
+ before(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
})
-
// GET /users/:id
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.get('/api/users/1')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
// 檢查是否回傳資料裡有 root 的資料
- res.body.name.should.equal('root');
+ res.body.name.should.equal('root')
- return done();
+ return done()
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
+ })
describe('GET /users/:id/tweets', () => {
- before(async() => {
+ before(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' })
})
// GET /users/:id/tweets - 看見某使用者發過的推文
- it(' - self successfully', (done) => {
+ it(' - self successfully', done => {
request(app)
.get('/api/users/1/tweets')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
- expect(res.body).to.be.an('array');
+ expect(res.body).to.be.an('array')
// 有回傳某使用者的推文資料
- res.body[0].description.should.equal('User1 的 Tweet1');
+ res.body[0].description.should.equal('User1 的 Tweet1')
- return done();
+ return done()
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
+ })
describe('GET /users/:id/replied_tweets', () => {
- before(async() => {
+ before(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Reply.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Reply.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.Tweet.create({UserId: 1, description: 'User1 的 Tweet1'})
- await db.Reply.create({UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.Tweet.create({ UserId: 1, description: 'User1 的 Tweet1' })
+ await db.Reply.create({ UserId: 1, TweetId: 1, comment: 'Tweet1 的 comment' })
})
// GET /users/:id/replied_tweets - 看見某使用者發過回覆的推文
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.get('/api/users/1/replied_tweets')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
- expect(res.body).to.be.an('array');
+ expect(res.body).to.be.an('array')
// 有回傳 Tweet1 的 comment 這筆資料
- res.body[0].comment.should.equal('Tweet1 的 comment');
+ res.body[0].comment.should.equal('Tweet1 的 comment')
- return done();
+ return done()
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Reply.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Reply.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
+ })
describe('GET /users/:id/likes', () => {
- before(async() => {
+ before(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Like.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Like.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
- await db.Tweet.create({UserId: 2, description: 'User2 的 Tweet1'})
- await db.Like.create({UserId: 1, TweetId: 1})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
+ await db.Tweet.create({ UserId: 2, description: 'User2 的 Tweet1' })
+ await db.Like.create({ UserId: 1, TweetId: 1 })
})
- // GET /users/:id/likes - 看見某使用者點過的 Like
- it(' - successfully', (done) => {
+ // GET /users/:id/likes - 看見某使用者點過的 Like
+ it(' - successfully', done => {
request(app)
.get('/api/users/1/likes')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
- expect(res.body).to.be.an('array');
+ .end(function (err, res) {
+ if (err) return done(err)
+ expect(res.body).to.be.an('array')
// 檢查回傳資料是否有 TweetId = 1
- res.body[0].TweetId.should.equal(1);
+ res.body[0].TweetId.should.equal(1)
- return done();
+ return done()
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Like.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Like.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
+ })
describe('GET /users/:id/followings', () => {
- before(async() => {
+ before(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Followship.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Followship.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
- await db.Followship.create({followerId: 1, followingId: 2})
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
+ await db.Followship.create({ followerId: 1, followingId: 2 })
})
// GET /users/:id/followings - 看見某使用者跟隨中的人
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.get('/api/users/1/followings')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
- expect(res.body).to.be.an('array');
- //回傳資料中是否有跟隨中的人的 id = 2
- res.body[0].followingId.should.equal(2);
+ expect(res.body).to.be.an('array')
+ // 回傳資料中是否有跟隨中的人的 id = 2
+ res.body[0].followingId.should.equal(2)
- return done();
+ return done()
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Followship.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Followship.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
+ })
describe('GET /users/:id/followers', () => {
- before(async() => {
+ before(async () => {
// 清除測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Followship.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Followship.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1'})
- await db.User.create({account: 'User2', name: 'User2', email: 'User2', password: 'User2'})
- await db.Followship.create({followerId: 1, followingId: 2})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1' })
+ await db.User.create({ account: 'User2', name: 'User2', email: 'User2', password: 'User2' })
+ await db.Followship.create({ followerId: 1, followingId: 2 })
})
// GET /users/:id/followers - 看見某使用者的跟隨者
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.get('/api/users/2/followers')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
- expect(res.body).to.be.an('array');
+ expect(res.body).to.be.an('array')
// 有跟隨者的 followerId = 1
- res.body[0].followerId.should.equal(1);
+ res.body[0].followerId.should.equal(1)
- return done();
+ return done()
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.Tweet.destroy({where: {},truncate: true, force: true})
- await db.Followship.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.Tweet.destroy({ where: {}, truncate: true, force: true })
+ await db.Followship.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
-
- });
-
+ })
+ })
context('# PUT ', () => {
-
describe('PUT /api/users/:id', () => {
- before(async() => {
+ before(async () => {
// 清除 User, Tweet table 的測試資料庫資料
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
// 模擬登入資料
- const rootUser = await db.User.create({name: 'root'});this.authenticate = sinon.stub(passport,"authenticate").callsFake((strategy, options, callback) => {
- callback(null, {...rootUser}, null);
- return (req,res,next)=>{};
- });
+ const rootUser = await db.User.create({ name: 'root' }); this.authenticate = sinon.stub(passport, 'authenticate').callsFake((strategy, options, callback) => {
+ callback(null, { ...rootUser }, null)
+ return (req, res, next) => {}
+ })
this.getUser = sinon.stub(
- helpers, 'getUser'
- ).returns({id: 1, Followings: [], role: 'user'});
+ helpers, 'getUser'
+ ).returns({ id: 1, Followings: [], role: 'user' })
// 在測試資料庫中,新增 mock 資料
- await db.User.create({account: 'User1', name: 'User1', email: 'User1', password: 'User1', introduction: 'User1'})
+ await db.User.create({ account: 'User1', name: 'User1', email: 'User1', password: 'User1', introduction: 'User1' })
})
// 編輯自己所有的資料 PUT /users/:id
- it(' - successfully', (done) => {
+ it(' - successfully', done => {
request(app)
.put('/api/users/1')
.send('name=User11&introduction=User11')
.set('Accept', 'application/json')
.expect(200)
- .end(function(err, res) {
- if (err) return done(err);
+ .end(function (err, res) {
+ if (err) return done(err)
db.User.findByPk(1).then(user => {
// 檢查資料是否有變更
- user.name.should.equal('User11');
- user.introduction.should.equal('User11');
- return done();
+ user.name.should.equal('User11')
+ user.introduction.should.equal('User11')
+ return done()
})
})
- });
+ })
after(async () => {
// 清除登入及測試資料庫資料
- this.authenticate.restore();
- this.getUser.restore();
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true });
- await db.User.destroy({where: {},truncate: true, force: true})
- await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true });
+ this.authenticate.restore()
+ this.getUser.restore()
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null, { raw: true })
+ await db.User.destroy({ where: {}, truncate: true, force: true })
+ await db.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null, { raw: true })
})
-
- });
-
- });
-
-});
\ No newline at end of file
+ })
+ })
+})