From a2df6a46bdc38176dacc8cee1a2e28783fd9af53 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Sun, 31 Oct 2021 13:04:23 +0800 Subject: [PATCH 001/101] remove other test and rename A17 -> R01 --- tests/A19.test.js | 164 ----------------------------- tests/A20.test.js | 72 ------------- tests/A21.test.js | 113 -------------------- tests/A22.test.js | 158 --------------------------- tests/{A17.test.js => R01.test.js} | 4 +- 5 files changed, 2 insertions(+), 509 deletions(-) delete mode 100644 tests/A19.test.js delete mode 100644 tests/A20.test.js delete mode 100644 tests/A21.test.js delete mode 100644 tests/A22.test.js rename tests/{A17.test.js => R01.test.js} (98%) diff --git a/tests/A19.test.js b/tests/A19.test.js deleted file mode 100644 index 228aafad..00000000 --- a/tests/A19.test.js +++ /dev/null @@ -1,164 +0,0 @@ -const chai = require('chai') -const request = require('supertest') -const sinon = require('sinon') -const should = chai.should() - -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} -describe('# A19', () => { - describe('# A19: 建立 User Profile', function () { - context('# [瀏覽 Profile]', () => { - // 前置準備 - before(() => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1 }) - // 製作假資料 - // 本 context 會用這筆資料進行測試 - this.UserMock = createModelMock('User', { - id: 1, - email: 'root@example.com', - name: 'admin', - isAdmin: false, - }) - - // 修改 userController 中的資料庫連線設定,由連向真實的資料庫 -> 改為連向模擬的 User table - this.userController = createControllerProxy('../../controllers/userController', { User: this.UserMock }) - }) - - // 開始測試 - it(' GET /users/:id ', async () => { - // 模擬 request & response - const req = mockRequest({ params: { id: 1 } }) // 帶入 params.id = 1,對 GET /users/1 發出請求 - const res = mockResponse() - - // 測試作業指定的 userController.getUser 函式 - await this.userController.getUser(req, res) - - // toggleAdmin 執行完畢後,應呼叫 res.render - // res.render 的第 1 個參數要是 'profile' - // res.render 的第 2 個參數要是 user,其 name 屬性的值應是 'admin' - res.render.getCall(0).args[0].should.equal('profile') - res.render.getCall(0).args[1].user.name.should.equal('admin') - }) - - // 測試完畢,清除資料 - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) - - context('# [瀏覽編輯 Profile 頁面]', () => { - before(() => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1 }) - - // 製作假資料 - // 本 context 會用這筆資料進行測試 - this.UserMock = createModelMock('User', { - id: 1, - email: 'root@example.com', - name: 'admin', - isAdmin: false, - }) - - // 連向模擬的 User table - this.userController = createControllerProxy('../../controllers/userController', { User: this.UserMock }) - }) - - it(' GET /users/:id/edit ', async () => { - // 模擬 request & response - const req = mockRequest({ params: { id: 1 } }) // 帶入 params.id = 1,對 GET /users/1/edit 發出請求 - const res = mockResponse() - - // 測試作業指定的 adminController.editUser 函式 - await this.userController.editUser(req, res) - - // editUser 執行完畢後,應呼叫 res.render - // res.render 的第 1 個參數要是 'edit' - // res.render 的第 2 個參數要是 user,其 name 屬性的值應是 'admin' - res.render.getCall(0).args[0].should.equal('edit') - res.render.getCall(0).args[1].user.name.should.equal('admin') - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) - - context('# [編輯 Profile]', () => { - before(async () => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1 }) - // 製作假資料 - // 本 context 會用這筆資料進行測試 - this.UserMock = createModelMock( - 'User', - { - id: 1, - email: 'root@example.com', - name: 'admin', - isAdmin: false, - } - ) - - // 連向模擬的 User table - this.userController = createControllerProxy('../../controllers/userController', { User: this.UserMock }) - }) - - it(' PUT /users/:id ', async () => { - // 模擬 request & response - // 對 PUT /users/1 發出 request,並夾帶 body.name = amdin2, body.email = admin_test@gmail.com - const req = mockRequest({ - params: { id: 1 }, - body: { name: 'admin2', email: 'admin_test@gmail.com' }, - }) - const res = mockResponse() - - // 測試作業指定的 userController.putUser 函式 - await this.userController.putUser(req, res) - - // putUser 正確執行的話,應呼叫 req.flash - // req.flash 的參數應與下列字串一致 - req.flash.calledWith('success_messages','使用者資料編輯成功').should.be.true - // putUser 執行完畢後,應呼叫 res.redirect 並重新導向 /users/1 - res.redirect.calledWith('/users/1').should.be.true - // putUser 執行完畢後,id:1 使用者的 name 和 email 應該已被修改 - // 將假資料撈出,比對確認有成功修改到 - const user = await this.UserMock.findOne({ where: { id: 1 } }) - user.name.should.equal('admin2') - user.email.should.equal('admin_test@gmail.com') - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) - }) -}) diff --git a/tests/A20.test.js b/tests/A20.test.js deleted file mode 100644 index a832e034..00000000 --- a/tests/A20.test.js +++ /dev/null @@ -1,72 +0,0 @@ -const chai = require('chai') -const request = require('supertest') -const sinon = require('sinon') -const should = chai.should() - -const helpers = require('../_helpers') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} - -describe('# A20: 餐廳資訊整理:Dashboard', function () { - context('# [Q1: Dashboard - 1 - controller / view / route]', () => { - before(async () => { - // 製作假資料 - // 本 context 會用這筆資料進行測試 - this.UserMock = createModelMock('User', { - id: 1, - email: 'root@example.com', - name: 'admin', - isAdmin: false, - }) - this.RestaurantMock = createModelMock('Restaurant', { - id: 1, - name: '銷魂麵', - viewCounts: 3 - }) - this.CategoryMock = createModelMock('Category', { - id: 1, - name: '食物' - }) - this.CommentMock = createModelMock('Comment', { - id: 1, - text: "gogogo" - }) - - // 連向模擬的 tables - this.restController = createControllerProxy('../controllers/restController', { - User: this.UserMock, - Category: this.CategoryMock, - Restaurant: this.RestaurantMock, - Comment: this.CommentMock, - }) - }) - - it(' GET /restaurants/:id/dashboard ', async () => { - // 模擬 request & response - const req = mockRequest({ params: { id: 1 } }) // 帶入 params.id = 1,對 GET /restaurants/1/dashboard 發出請求 - const res = mockResponse() - // 測試 restController.getDashBoard 函式 - await this.restController.getDashBoard(req, res) - - // getDashBoard 執行完畢後,應呼叫 res.render - // res.render 的第 1 個參數要是 'dashboard' - // res.render 的第 2 個參數要包含 restaurant,其 name 屬性的值應是 '銷魂麵' - // res.render 的地 3 個參數要包含 restaurant,其 viewCounts 值應該是 3 - res.render.getCall(0).args[0].should.equal('dashboard') - res.render.getCall(0).args[1].restaurant.name.should.equal('銷魂麵') - res.render.getCall(0).args[1].restaurant.viewCounts.should.equal(3) - }) - }) -}) diff --git a/tests/A21.test.js b/tests/A21.test.js deleted file mode 100644 index ee638370..00000000 --- a/tests/A21.test.js +++ /dev/null @@ -1,113 +0,0 @@ -const chai = require('chai') -const request = require('supertest') -const sinon = require('sinon') -const should = chai.should() - -const db = require('../models') -const helpers = require('../_helpers') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers') - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} - -// 建立模擬的 Like 資料 -let mockLikeData = [ - { - userId: 1, - restaurantId: 2, - }, -] - -describe('# A21: Like / Unlike', function () { - context('# Q1: 使用者可以 Like 餐廳', () => { - before(() => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1 }) - - // 建立了一個模擬的 Like table,裡面目前是空的 - this.mockLikeData = [] - this.likeMock = createModelMock('Like', null, this.mockLikeData) - - // 連向模擬的 Like table - this.userController = createControllerProxy('../controllers/userController', {Like: this.likeMock}) - }) - - it(' POST /like/:restaurantId ', async () => { - // 模擬 request & response - const req = mockRequest({ params: { restaurantId: 2 } }) // 帶入 params.restaurantId = 2,對 POST /like/2 發出請求 - const res = mockResponse() - - // 測試 userController.addLike 函式 - await this.userController.addLike(req, res) - // 將模擬的 Like table 內的資料全數撈出 - const likes = await this.likeMock.findAll() - // addLike 執行完畢後,Like table 應會從空的 -> 變成有 1 筆資料 - likes.should.have.lengthOf(1) - // 資料裡的 UserId 應該會跟我們傳入的 user id 一樣 - likes[0].UserId.should.equal(1) - // 資料裡的 RestaurantId 會跟我們傳入的 params.restaurantId 一樣 - likes[0].RestaurantId.should.equal(2) - }) - - after(async () => { - // 清除驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) - - context('# Q1: 使用者可以 unLike 餐廳', () => { - before(() => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1 }) - // 製作假資料 - // 下個 context 會用這筆資料進行測試 - // 模擬 Like table 裡目前有 1 筆資料如下 - this.likeMock = createModelMock('Like', { - id: 1, - UserId: 1, - RestaurantId: 2, - }, mockLikeData); - - // 連向模擬的 Like table - this.userController = createControllerProxy('../controllers/userController', { Like: this.likeMock }) - }) - - it(' DELETE /like/:restaurantId ', async () => { - // 模擬 request & response - // 模擬發出 request, 帶入 params.id = 1, restaurantId = 2 - const req = mockRequest({ params: { id: 1, restaurantId: 2 } }) // 帶入 params.id = 1,對 DELETE /like/2 發出請求 - const res = mockResponse() - - // 測試作業指定的 userController.removeLike 函式 - await this.userController.removeLike(req, res) - - // 將模擬的 Like table 內的資料全數撈出 - const likes = await this.likeMock.findAll() - // addLike 執行完畢後,Like table 應會從有 1 筆資料 -> 變成空的 - likes.should.have.lengthOf(0) - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) -}) diff --git a/tests/A22.test.js b/tests/A22.test.js deleted file mode 100644 index 793e6996..00000000 --- a/tests/A22.test.js +++ /dev/null @@ -1,158 +0,0 @@ -const chai = require('chai') -const request = require('supertest') -const sinon = require('sinon') -const should = chai.should() - -const app = require('../app') -const helpers = require('../_helpers') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers') - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} -// 模擬 2 間餐廳資料 -let mockRestaurantData = [ - { - id: 1, - name: 'Restaurant1', - tel: 'tel', - address: 'address', - opening_hours: 'opening_hours', - description: 'test description', - favoritedUsers: [ - { - userId: 1, - }, - ], - }, - { - id: 2, - name: 'Restaurant2', - tel: 'tel', - address: 'address', - opening_hours: 'opening_hours', - description: 'description', - categoryId: 1, - favoritedUsers: [], - }, -] - -describe('# A22: TOP 10 人氣餐廳 ', function () { - context('# [網址正確、畫面正常執行]', () => { - before(async () => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - // 模擬 getUser 函式,負責取得使用者資料 - this.getUser = sinon - .stub(helpers, 'getUser') - .returns({ id: 1, followings: [], favoritedRestaurants: [] }) - }) - - it(' GET /restaurants/top ', (done) => { - // 對 GET /restaurants/top 發出請求 - request(app) - .get('/restaurants/top') - .end(function (err, res) { - // 回應中應包含字串'Top 10 人氣餐廳' - // 若請求路徑正確,controller 執行後,會呼叫 res.render - // res.render 回傳的 view 樣板裡應包含字串'Top 10 人氣餐廳' - res.text.should.include('Top 10 人氣餐廳') - done() - }) - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) - - context( - '# [當你點擊畫面上的「加入最愛 / 移除最愛」按鈕時,會重新計算「收藏數」的數字]', - () => { - before(async () => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - // 模擬 getUser 函式,負責取得使用者資料 - this.getUser = sinon - .stub(helpers, 'getUser') - .returns({ id: 1, followings: [], favoritedRestaurants: [] }) - - // 建立了一個模擬的 Restaurant table,裡面放入 2 間餐廳資料 - this.restaurantMock = createModelMock('Restaurant', null, mockRestaurantData) - - // 連向模擬的 Restaurant table - this.restController = createControllerProxy('../controllers/restController', { - Restaurant: this.restaurantMock, - }) - - // 建立了一個模擬的 Favorite table,裡面有 1 筆資料 - this.favoriteMock = createModelMock('Favorite', null, mockRestaurantData, 'FavoritedUsers') - - // 連向模擬的 Favorite table - this.userController = createControllerProxy('../controllers/userController', {Favorite: this.favoriteMock}) - }) - - it(' POST favorite ', async () => { - // 模擬 request & response - // 對 POST /favorite/2 發出請求,夾帶 user.favoritedRestaurants - const req = mockRequest({ - user: { favoritedRestaurants: [] }, - params: { restaurantId: 2 }, - }) - const res = mockResponse() - - // 測試 userController.addFavorite 函式 - await this.userController.addFavorite(req, res) - - // 取得餐廳排序資料 - await this.restController.getTopRestaurant(req, res) - - // addFavorite 執行完畢後,應呼叫 res.render - // res.render 的第 2 個參數要包含 restaurants - // restaurant 當中的第 2 筆資料 favoritedCount 屬性的值應是 1 (被 1 個使用者加入最愛了) - res.render.getCall(0).args[1].restaurants[1].favoritedCount.should.equal(1) - }) - - it(' DELETE favorite ', async () => { - // 模擬 request & response - // 對 DELETE /favorite/1 發出請求,夾入 user.favoritedRestaurants - const req = mockRequest({ - user: { favoritedRestaurants: [] }, - params: { restaurantId: 1 }, - }) - const res = mockResponse() - - // 測試 userController.removeFavorite 函式 - await this.userController.removeFavorite(req, res) - // 取得餐廳排序資料 - await this.restController.getTopRestaurant(req, res) - - // removeFavorite 執行完畢後,應呼叫 res.render - // res.render 的第 2 個參數要包含 restaurants - // restaurants 當中的第 1 筆資料 id 屬性值應是 2 (id:1 的那家餐廳被刪除了) - res.render.getCall(0).args[1].restaurants[0].id.should.equal(2) - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - } - ) -}) diff --git a/tests/A17.test.js b/tests/R01.test.js similarity index 98% rename from tests/A17.test.js rename to tests/R01.test.js index 6065446e..38d41967 100644 --- a/tests/A17.test.js +++ b/tests/R01.test.js @@ -19,7 +19,7 @@ const mockResponse = () => { } } -describe('# A17', () => { +describe('# R01', () => { describe('登入測試: POST /signin', function(){ // 以下測試會發出請求,測試資料庫內是否有作業指定的使用者資料 // 測試資料的來源是真實的資料庫 @@ -57,7 +57,7 @@ describe('# A17', () => { }) }); - describe('# A17: 使用者權限管理', function () { + describe('# R01: 使用者權限管理', function () { // 前置準備 before(() => { // 製作假資料 From d3a66ddaea0ef1bf0b9deda1454cb2fa2505d0db Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Sun, 31 Oct 2021 13:09:29 +0800 Subject: [PATCH 002/101] remove R03/04/05 test --- tests/R03.test.js | 72 --------------------- tests/R04.test.js | 113 --------------------------------- tests/R05.test.js | 158 ---------------------------------------------- 3 files changed, 343 deletions(-) delete mode 100644 tests/R03.test.js delete mode 100644 tests/R04.test.js delete mode 100644 tests/R05.test.js diff --git a/tests/R03.test.js b/tests/R03.test.js deleted file mode 100644 index bc7d1ade..00000000 --- a/tests/R03.test.js +++ /dev/null @@ -1,72 +0,0 @@ -const chai = require('chai') -const request = require('supertest') -const sinon = require('sinon') -const should = chai.should() - -const helpers = require('../_helpers') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} - -describe('# R03: 餐廳資訊整理:Dashboard', function () { - context('# [Q1: Dashboard - 1 - controller / view / route]', () => { - before(async () => { - // 製作假資料 - // 本 context 會用這筆資料進行測試 - this.UserMock = createModelMock('User', { - id: 1, - email: 'root@example.com', - name: 'admin', - isAdmin: false, - }) - this.RestaurantMock = createModelMock('Restaurant', { - id: 1, - name: '銷魂麵', - viewCounts: 3 - }) - this.CategoryMock = createModelMock('Category', { - id: 1, - name: '食物' - }) - this.CommentMock = createModelMock('Comment', { - id: 1, - text: "gogogo" - }) - - // 連向模擬的 tables - this.restController = createControllerProxy('../controllers/restController', { - User: this.UserMock, - Category: this.CategoryMock, - Restaurant: this.RestaurantMock, - Comment: this.CommentMock, - }) - }) - - it(' GET /restaurants/:id/dashboard ', async () => { - // 模擬 request & response - const req = mockRequest({ params: { id: 1 } }) // 帶入 params.id = 1,對 GET /restaurants/1/dashboard 發出請求 - const res = mockResponse() - // 測試 restController.getDashBoard 函式 - await this.restController.getDashBoard(req, res) - - // getDashBoard 執行完畢後,應呼叫 res.render - // res.render 的第 1 個參數要是 'dashboard' - // res.render 的第 2 個參數要包含 restaurant,其 name 屬性的值應是 '銷魂麵' - // res.render 的地 3 個參數要包含 restaurant,其 viewCounts 值應該是 3 - res.render.getCall(0).args[0].should.equal('dashboard') - res.render.getCall(0).args[1].restaurant.name.should.equal('銷魂麵') - res.render.getCall(0).args[1].restaurant.viewCounts.should.equal(3) - }) - }) -}) diff --git a/tests/R04.test.js b/tests/R04.test.js deleted file mode 100644 index 86bbb191..00000000 --- a/tests/R04.test.js +++ /dev/null @@ -1,113 +0,0 @@ -const chai = require('chai') -const request = require('supertest') -const sinon = require('sinon') -const should = chai.should() - -const db = require('../models') -const helpers = require('../_helpers') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers') - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} - -// 建立模擬的 Like 資料 -let mockLikeData = [ - { - userId: 1, - restaurantId: 2, - }, -] - -describe('# R04: Like / Unlike', function () { - context('# Q1: 使用者可以 Like 餐廳', () => { - before(() => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1 }) - - // 建立了一個模擬的 Like table,裡面目前是空的 - this.mockLikeData = [] - this.likeMock = createModelMock('Like', null, this.mockLikeData) - - // 連向模擬的 Like table - this.userController = createControllerProxy('../controllers/userController', {Like: this.likeMock}) - }) - - it(' POST /like/:restaurantId ', async () => { - // 模擬 request & response - const req = mockRequest({ params: { restaurantId: 2 } }) // 帶入 params.restaurantId = 2,對 POST /like/2 發出請求 - const res = mockResponse() - - // 測試 userController.addLike 函式 - await this.userController.addLike(req, res) - // 將模擬的 Like table 內的資料全數撈出 - const likes = await this.likeMock.findAll() - // addLike 執行完畢後,Like table 應會從空的 -> 變成有 1 筆資料 - likes.should.have.lengthOf(1) - // 資料裡的 UserId 應該會跟我們傳入的 user id 一樣 - likes[0].UserId.should.equal(1) - // 資料裡的 RestaurantId 會跟我們傳入的 params.restaurantId 一樣 - likes[0].RestaurantId.should.equal(2) - }) - - after(async () => { - // 清除驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) - - context('# Q1: 使用者可以 unLike 餐廳', () => { - before(() => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1 }) - // 製作假資料 - // 下個 context 會用這筆資料進行測試 - // 模擬 Like table 裡目前有 1 筆資料如下 - this.likeMock = createModelMock('Like', { - id: 1, - UserId: 1, - RestaurantId: 2, - }, mockLikeData); - - // 連向模擬的 Like table - this.userController = createControllerProxy('../controllers/userController', { Like: this.likeMock }) - }) - - it(' DELETE /like/:restaurantId ', async () => { - // 模擬 request & response - // 模擬發出 request, 帶入 params.id = 1, restaurantId = 2 - const req = mockRequest({ params: { id: 1, restaurantId: 2 } }) // 帶入 params.id = 1,對 DELETE /like/2 發出請求 - const res = mockResponse() - - // 測試作業指定的 userController.removeLike 函式 - await this.userController.removeLike(req, res) - - // 將模擬的 Like table 內的資料全數撈出 - const likes = await this.likeMock.findAll() - // addLike 執行完畢後,Like table 應會從有 1 筆資料 -> 變成空的 - likes.should.have.lengthOf(0) - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) -}) diff --git a/tests/R05.test.js b/tests/R05.test.js deleted file mode 100644 index a0ef79cc..00000000 --- a/tests/R05.test.js +++ /dev/null @@ -1,158 +0,0 @@ -const chai = require('chai') -const request = require('supertest') -const sinon = require('sinon') -const should = chai.should() - -const app = require('../app') -const helpers = require('../_helpers') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers') - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} -// 模擬 2 間餐廳資料 -let mockRestaurantData = [ - { - id: 1, - name: 'Restaurant1', - tel: 'tel', - address: 'address', - opening_hours: 'opening_hours', - description: 'test description', - favoritedUsers: [ - { - userId: 1, - }, - ], - }, - { - id: 2, - name: 'Restaurant2', - tel: 'tel', - address: 'address', - opening_hours: 'opening_hours', - description: 'description', - categoryId: 1, - favoritedUsers: [], - }, -] - -describe('# R05: TOP 10 人氣餐廳 ', function () { - context('# [網址正確、畫面正常執行]', () => { - before(async () => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - // 模擬 getUser 函式,負責取得使用者資料 - this.getUser = sinon - .stub(helpers, 'getUser') - .returns({ id: 1, followings: [], favoritedRestaurants: [] }) - }) - - it(' GET /restaurants/top ', (done) => { - // 對 GET /restaurants/top 發出請求 - request(app) - .get('/restaurants/top') - .end(function (err, res) { - // 回應中應包含字串'Top 10 人氣餐廳' - // 若請求路徑正確,controller 執行後,會呼叫 res.render - // res.render 回傳的 view 樣板裡應包含字串'Top 10 人氣餐廳' - res.text.should.include('Top 10 人氣餐廳') - done() - }) - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) - - context( - '# [當你點擊畫面上的「加入最愛 / 移除最愛」按鈕時,會重新計算「收藏數」的數字]', - () => { - before(async () => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - // 模擬 getUser 函式,負責取得使用者資料 - this.getUser = sinon - .stub(helpers, 'getUser') - .returns({ id: 1, followings: [], favoritedRestaurants: [] }) - - // 建立了一個模擬的 Restaurant table,裡面放入 2 間餐廳資料 - this.restaurantMock = createModelMock('Restaurant', null, mockRestaurantData) - - // 連向模擬的 Restaurant table - this.restController = createControllerProxy('../controllers/restController', { - Restaurant: this.restaurantMock, - }) - - // 建立了一個模擬的 Favorite table,裡面有 1 筆資料 - this.favoriteMock = createModelMock('Favorite', null, mockRestaurantData, 'FavoritedUsers') - - // 連向模擬的 Favorite table - this.userController = createControllerProxy('../controllers/userController', {Favorite: this.favoriteMock}) - }) - - it(' POST favorite ', async () => { - // 模擬 request & response - // 對 POST /favorite/2 發出請求,夾帶 user.favoritedRestaurants - const req = mockRequest({ - user: { favoritedRestaurants: [] }, - params: { restaurantId: 2 }, - }) - const res = mockResponse() - - // 測試 userController.addFavorite 函式 - await this.userController.addFavorite(req, res) - - // 取得餐廳排序資料 - await this.restController.getTopRestaurant(req, res) - - // addFavorite 執行完畢後,應呼叫 res.render - // res.render 的第 2 個參數要包含 restaurants - // restaurant 當中的第 2 筆資料 favoritedCount 屬性的值應是 1 (被 1 個使用者加入最愛了) - res.render.getCall(0).args[1].restaurants[1].favoritedCount.should.equal(1) - }) - - it(' DELETE favorite ', async () => { - // 模擬 request & response - // 對 DELETE /favorite/1 發出請求,夾入 user.favoritedRestaurants - const req = mockRequest({ - user: { favoritedRestaurants: [] }, - params: { restaurantId: 1 }, - }) - const res = mockResponse() - - // 測試 userController.removeFavorite 函式 - await this.userController.removeFavorite(req, res) - // 取得餐廳排序資料 - await this.restController.getTopRestaurant(req, res) - - // removeFavorite 執行完畢後,應呼叫 res.render - // res.render 的第 2 個參數要包含 restaurants - // restaurants 當中的第 1 筆資料 id 屬性值應是 2 (id:1 的那家餐廳被刪除了) - res.render.getCall(0).args[1].restaurants[0].id.should.equal(2) - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - } - ) -}) From e0dbcb62099ea60df1e6da8f56596b7190488f84 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Sun, 31 Oct 2021 13:10:14 +0800 Subject: [PATCH 003/101] remove R04/05 test --- tests/R04.test.js | 113 --------------------------------- tests/R05.test.js | 158 ---------------------------------------------- 2 files changed, 271 deletions(-) delete mode 100644 tests/R04.test.js delete mode 100644 tests/R05.test.js diff --git a/tests/R04.test.js b/tests/R04.test.js deleted file mode 100644 index 86bbb191..00000000 --- a/tests/R04.test.js +++ /dev/null @@ -1,113 +0,0 @@ -const chai = require('chai') -const request = require('supertest') -const sinon = require('sinon') -const should = chai.should() - -const db = require('../models') -const helpers = require('../_helpers') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers') - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} - -// 建立模擬的 Like 資料 -let mockLikeData = [ - { - userId: 1, - restaurantId: 2, - }, -] - -describe('# R04: Like / Unlike', function () { - context('# Q1: 使用者可以 Like 餐廳', () => { - before(() => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1 }) - - // 建立了一個模擬的 Like table,裡面目前是空的 - this.mockLikeData = [] - this.likeMock = createModelMock('Like', null, this.mockLikeData) - - // 連向模擬的 Like table - this.userController = createControllerProxy('../controllers/userController', {Like: this.likeMock}) - }) - - it(' POST /like/:restaurantId ', async () => { - // 模擬 request & response - const req = mockRequest({ params: { restaurantId: 2 } }) // 帶入 params.restaurantId = 2,對 POST /like/2 發出請求 - const res = mockResponse() - - // 測試 userController.addLike 函式 - await this.userController.addLike(req, res) - // 將模擬的 Like table 內的資料全數撈出 - const likes = await this.likeMock.findAll() - // addLike 執行完畢後,Like table 應會從空的 -> 變成有 1 筆資料 - likes.should.have.lengthOf(1) - // 資料裡的 UserId 應該會跟我們傳入的 user id 一樣 - likes[0].UserId.should.equal(1) - // 資料裡的 RestaurantId 會跟我們傳入的 params.restaurantId 一樣 - likes[0].RestaurantId.should.equal(2) - }) - - after(async () => { - // 清除驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) - - context('# Q1: 使用者可以 unLike 餐廳', () => { - before(() => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - this.getUser = sinon.stub(helpers, 'getUser').returns({ id: 1 }) - // 製作假資料 - // 下個 context 會用這筆資料進行測試 - // 模擬 Like table 裡目前有 1 筆資料如下 - this.likeMock = createModelMock('Like', { - id: 1, - UserId: 1, - RestaurantId: 2, - }, mockLikeData); - - // 連向模擬的 Like table - this.userController = createControllerProxy('../controllers/userController', { Like: this.likeMock }) - }) - - it(' DELETE /like/:restaurantId ', async () => { - // 模擬 request & response - // 模擬發出 request, 帶入 params.id = 1, restaurantId = 2 - const req = mockRequest({ params: { id: 1, restaurantId: 2 } }) // 帶入 params.id = 1,對 DELETE /like/2 發出請求 - const res = mockResponse() - - // 測試作業指定的 userController.removeLike 函式 - await this.userController.removeLike(req, res) - - // 將模擬的 Like table 內的資料全數撈出 - const likes = await this.likeMock.findAll() - // addLike 執行完畢後,Like table 應會從有 1 筆資料 -> 變成空的 - likes.should.have.lengthOf(0) - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) -}) diff --git a/tests/R05.test.js b/tests/R05.test.js deleted file mode 100644 index a0ef79cc..00000000 --- a/tests/R05.test.js +++ /dev/null @@ -1,158 +0,0 @@ -const chai = require('chai') -const request = require('supertest') -const sinon = require('sinon') -const should = chai.should() - -const app = require('../app') -const helpers = require('../_helpers') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers') - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} -// 模擬 2 間餐廳資料 -let mockRestaurantData = [ - { - id: 1, - name: 'Restaurant1', - tel: 'tel', - address: 'address', - opening_hours: 'opening_hours', - description: 'test description', - favoritedUsers: [ - { - userId: 1, - }, - ], - }, - { - id: 2, - name: 'Restaurant2', - tel: 'tel', - address: 'address', - opening_hours: 'opening_hours', - description: 'description', - categoryId: 1, - favoritedUsers: [], - }, -] - -describe('# R05: TOP 10 人氣餐廳 ', function () { - context('# [網址正確、畫面正常執行]', () => { - before(async () => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - // 模擬 getUser 函式,負責取得使用者資料 - this.getUser = sinon - .stub(helpers, 'getUser') - .returns({ id: 1, followings: [], favoritedRestaurants: [] }) - }) - - it(' GET /restaurants/top ', (done) => { - // 對 GET /restaurants/top 發出請求 - request(app) - .get('/restaurants/top') - .end(function (err, res) { - // 回應中應包含字串'Top 10 人氣餐廳' - // 若請求路徑正確,controller 執行後,會呼叫 res.render - // res.render 回傳的 view 樣板裡應包含字串'Top 10 人氣餐廳' - res.text.should.include('Top 10 人氣餐廳') - done() - }) - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - }) - - context( - '# [當你點擊畫面上的「加入最愛 / 移除最愛」按鈕時,會重新計算「收藏數」的數字]', - () => { - before(async () => { - // 模擬登入驗證 - this.ensureAuthenticated = sinon - .stub(helpers, 'ensureAuthenticated') - .returns(true) - // 模擬 getUser 函式,負責取得使用者資料 - this.getUser = sinon - .stub(helpers, 'getUser') - .returns({ id: 1, followings: [], favoritedRestaurants: [] }) - - // 建立了一個模擬的 Restaurant table,裡面放入 2 間餐廳資料 - this.restaurantMock = createModelMock('Restaurant', null, mockRestaurantData) - - // 連向模擬的 Restaurant table - this.restController = createControllerProxy('../controllers/restController', { - Restaurant: this.restaurantMock, - }) - - // 建立了一個模擬的 Favorite table,裡面有 1 筆資料 - this.favoriteMock = createModelMock('Favorite', null, mockRestaurantData, 'FavoritedUsers') - - // 連向模擬的 Favorite table - this.userController = createControllerProxy('../controllers/userController', {Favorite: this.favoriteMock}) - }) - - it(' POST favorite ', async () => { - // 模擬 request & response - // 對 POST /favorite/2 發出請求,夾帶 user.favoritedRestaurants - const req = mockRequest({ - user: { favoritedRestaurants: [] }, - params: { restaurantId: 2 }, - }) - const res = mockResponse() - - // 測試 userController.addFavorite 函式 - await this.userController.addFavorite(req, res) - - // 取得餐廳排序資料 - await this.restController.getTopRestaurant(req, res) - - // addFavorite 執行完畢後,應呼叫 res.render - // res.render 的第 2 個參數要包含 restaurants - // restaurant 當中的第 2 筆資料 favoritedCount 屬性的值應是 1 (被 1 個使用者加入最愛了) - res.render.getCall(0).args[1].restaurants[1].favoritedCount.should.equal(1) - }) - - it(' DELETE favorite ', async () => { - // 模擬 request & response - // 對 DELETE /favorite/1 發出請求,夾入 user.favoritedRestaurants - const req = mockRequest({ - user: { favoritedRestaurants: [] }, - params: { restaurantId: 1 }, - }) - const res = mockResponse() - - // 測試 userController.removeFavorite 函式 - await this.userController.removeFavorite(req, res) - // 取得餐廳排序資料 - await this.restController.getTopRestaurant(req, res) - - // removeFavorite 執行完畢後,應呼叫 res.render - // res.render 的第 2 個參數要包含 restaurants - // restaurants 當中的第 1 筆資料 id 屬性值應是 2 (id:1 的那家餐廳被刪除了) - res.render.getCall(0).args[1].restaurants[0].id.should.equal(2) - }) - - after(async () => { - // 清除模擬驗證資料 - this.ensureAuthenticated.restore() - this.getUser.restore() - }) - } - ) -}) From 3a5beed45cf3d7763ae0a192b2878942b0e2804b Mon Sep 17 00:00:00 2001 From: Carrot7712 Date: Mon, 1 Nov 2021 13:31:28 +0800 Subject: [PATCH 004/101] update cofig.json --- config/config.json | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/config/config.json b/config/config.json index 56636a1c..987b7880 100644 --- a/config/config.json +++ b/config/config.json @@ -6,16 +6,12 @@ "host": "127.0.0.1", "dialect": "mysql" }, - "test": { + "production": { "username": "root", - "password": "password", - "database": "forum_test", + "password": null, + "database": "database_production", "host": "127.0.0.1", - "dialect": "mysql", - "logging": false - }, - "production": { - "use_env_variable": "CLEARDB_SILVER_URL" + "dialect": "mysql" }, "travis": { "username": "travis", @@ -24,4 +20,5 @@ "dialect": "mysql", "logging": false } -} \ No newline at end of file +} + From 914871590b449f471147579952f39df72512e664 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 15:14:53 +0800 Subject: [PATCH 005/101] fixed R01 ../../app issue & not found sequelize lib --- tests/R01.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index 38d41967..07778434 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -3,8 +3,7 @@ const request = require('supertest') const sinon = require('sinon') const should = chai.should() -const app = require('../../app') -const { classToInvokable } = require('sequelize/types/lib/utils') +const app = require('../app') const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); const mockRequest = (query) => { From 154a12e2d4cba762c014fe35bfb60f6f3df16455 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 15:14:53 +0800 Subject: [PATCH 006/101] fixed R01 ../../app issue & not found sequelize lib --- tests/R01.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index 38d41967..07778434 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -3,8 +3,7 @@ const request = require('supertest') const sinon = require('sinon') const should = chai.should() -const app = require('../../app') -const { classToInvokable } = require('sequelize/types/lib/utils') +const app = require('../app') const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); const mockRequest = (query) => { From c3b664cfbf2217fb7b006dd920a53660c8f46f05 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 15:14:53 +0800 Subject: [PATCH 007/101] fixed R01 ../../app issue & not found sequelize lib --- tests/R01.test.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index 38d41967..07778434 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -3,8 +3,7 @@ const request = require('supertest') const sinon = require('sinon') const should = chai.should() -const app = require('../../app') -const { classToInvokable } = require('sequelize/types/lib/utils') +const app = require('../app') const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); const mockRequest = (query) => { From ba687334daaf8456d0585b52418ffbe090ad7ca0 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 20:17:36 +0800 Subject: [PATCH 008/101] fixed controller path wrong issue / check data exist --- helpers/unitTestHelpers.js | 4 ++-- tests/R01.test.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index a7157681..ea4cc7b1 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -32,7 +32,7 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(data.map(d => mockModel.build(d))) } else if (query === 'findAll') { // 回傳模擬資料 - return Promise.resolve(data.map(d => mockModel.build(d))) + return Promise.resolve( data ? data.map(d => mockModel.build(d)) : []) }else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 // 因此就可以模擬將模擬資料中的資料刪除 @@ -56,7 +56,7 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(mockModel.build(data)) } else if (query === 'findAll') { // 回傳模擬資料 - return Promise.resolve(data.map(d => mockModel.build(d))) + return Promise.resolve(data ? data.map(d => mockModel.build(d)) : []) } else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 // 因此就可以模擬將模擬資料中的資料刪除 diff --git a/tests/R01.test.js b/tests/R01.test.js index 07778434..f98a96ac 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -69,7 +69,7 @@ describe('# R01', () => { }) // 修改 adminController 中的資料庫連線設定,由連向真實的資料庫 -> 改為連向模擬的 User table - this.adminController = createControllerProxy('../../controllers/adminController', { User: this.UserMock }) + this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) // 開始測試 @@ -104,7 +104,7 @@ describe('# R01', () => { ) // 將 adminController 中的 User db 取代成 User mock db - this.adminController = createControllerProxy('../../controllers/adminController', { User: this.UserMock }) + this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) it(' PUT /admin/users/:id/toggleAdmin ', async () => { @@ -138,7 +138,7 @@ describe('# R01', () => { } ) // 將 adminController 中的 User db 取代成 User mock db - this.adminController = createControllerProxy('../../controllers/adminController', { User: this.UserMock }) + this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) it(' PUT /admin/users/:id/toggleAdmin ', async (done) => { From 3f256dcc2ba68a58e22bf6ae1fd3cf95ee3c6ab3 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 20:17:36 +0800 Subject: [PATCH 009/101] fixed controller path wrong issue / check data exist --- helpers/unitTestHelpers.js | 4 ++-- tests/R01.test.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index a7157681..ea4cc7b1 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -32,7 +32,7 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(data.map(d => mockModel.build(d))) } else if (query === 'findAll') { // 回傳模擬資料 - return Promise.resolve(data.map(d => mockModel.build(d))) + return Promise.resolve( data ? data.map(d => mockModel.build(d)) : []) }else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 // 因此就可以模擬將模擬資料中的資料刪除 @@ -56,7 +56,7 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(mockModel.build(data)) } else if (query === 'findAll') { // 回傳模擬資料 - return Promise.resolve(data.map(d => mockModel.build(d))) + return Promise.resolve(data ? data.map(d => mockModel.build(d)) : []) } else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 // 因此就可以模擬將模擬資料中的資料刪除 diff --git a/tests/R01.test.js b/tests/R01.test.js index 07778434..f98a96ac 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -69,7 +69,7 @@ describe('# R01', () => { }) // 修改 adminController 中的資料庫連線設定,由連向真實的資料庫 -> 改為連向模擬的 User table - this.adminController = createControllerProxy('../../controllers/adminController', { User: this.UserMock }) + this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) // 開始測試 @@ -104,7 +104,7 @@ describe('# R01', () => { ) // 將 adminController 中的 User db 取代成 User mock db - this.adminController = createControllerProxy('../../controllers/adminController', { User: this.UserMock }) + this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) it(' PUT /admin/users/:id/toggleAdmin ', async () => { @@ -138,7 +138,7 @@ describe('# R01', () => { } ) // 將 adminController 中的 User db 取代成 User mock db - this.adminController = createControllerProxy('../../controllers/adminController', { User: this.UserMock }) + this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) it(' PUT /admin/users/:id/toggleAdmin ', async (done) => { From 0ab85cd3943e1de42f1ef8992ade086c6b8f4680 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 20:21:36 +0800 Subject: [PATCH 010/101] fixed wrong path --- tests/R02.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/R02.test.js b/tests/R02.test.js index ea3739e9..5b7cadb2 100644 --- a/tests/R02.test.js +++ b/tests/R02.test.js @@ -37,7 +37,7 @@ describe('# R02', () => { }) // 修改 userController 中的資料庫連線設定,由連向真實的資料庫 -> 改為連向模擬的 User table - this.userController = createControllerProxy('../../controllers/userController', { User: this.UserMock }) + this.userController = createControllerProxy('../controllers/userController', { User: this.UserMock }) }) // 開始測試 @@ -82,7 +82,7 @@ describe('# R02', () => { }) // 連向模擬的 User table - this.userController = createControllerProxy('../../controllers/userController', { User: this.UserMock }) + this.userController = createControllerProxy('../controllers/userController', { User: this.UserMock }) }) it(' GET /users/:id/edit ', async () => { @@ -127,7 +127,7 @@ describe('# R02', () => { ) // 連向模擬的 User table - this.userController = createControllerProxy('../../controllers/userController', { User: this.UserMock }) + this.userController = createControllerProxy('../controllers/userController', { User: this.UserMock }) }) it(' PUT /users/:id ', async () => { From a342d2d97f2da6c14d7386ae1a8df939340da73f Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 20:17:36 +0800 Subject: [PATCH 011/101] fixed controller path wrong issue / check data exist --- helpers/unitTestHelpers.js | 4 ++-- tests/R01.test.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index a7157681..ea4cc7b1 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -32,7 +32,7 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(data.map(d => mockModel.build(d))) } else if (query === 'findAll') { // 回傳模擬資料 - return Promise.resolve(data.map(d => mockModel.build(d))) + return Promise.resolve( data ? data.map(d => mockModel.build(d)) : []) }else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 // 因此就可以模擬將模擬資料中的資料刪除 @@ -56,7 +56,7 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(mockModel.build(data)) } else if (query === 'findAll') { // 回傳模擬資料 - return Promise.resolve(data.map(d => mockModel.build(d))) + return Promise.resolve(data ? data.map(d => mockModel.build(d)) : []) } else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 // 因此就可以模擬將模擬資料中的資料刪除 diff --git a/tests/R01.test.js b/tests/R01.test.js index 07778434..f98a96ac 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -69,7 +69,7 @@ describe('# R01', () => { }) // 修改 adminController 中的資料庫連線設定,由連向真實的資料庫 -> 改為連向模擬的 User table - this.adminController = createControllerProxy('../../controllers/adminController', { User: this.UserMock }) + this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) // 開始測試 @@ -104,7 +104,7 @@ describe('# R01', () => { ) // 將 adminController 中的 User db 取代成 User mock db - this.adminController = createControllerProxy('../../controllers/adminController', { User: this.UserMock }) + this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) it(' PUT /admin/users/:id/toggleAdmin ', async () => { @@ -138,7 +138,7 @@ describe('# R01', () => { } ) // 將 adminController 中的 User db 取代成 User mock db - this.adminController = createControllerProxy('../../controllers/adminController', { User: this.UserMock }) + this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) it(' PUT /admin/users/:id/toggleAdmin ', async (done) => { From b10ee15ef5278be8d5b747177f00b3371fea90f2 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 20:21:36 +0800 Subject: [PATCH 012/101] fixed wrong path --- tests/R02.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/R02.test.js b/tests/R02.test.js index ea3739e9..5b7cadb2 100644 --- a/tests/R02.test.js +++ b/tests/R02.test.js @@ -37,7 +37,7 @@ describe('# R02', () => { }) // 修改 userController 中的資料庫連線設定,由連向真實的資料庫 -> 改為連向模擬的 User table - this.userController = createControllerProxy('../../controllers/userController', { User: this.UserMock }) + this.userController = createControllerProxy('../controllers/userController', { User: this.UserMock }) }) // 開始測試 @@ -82,7 +82,7 @@ describe('# R02', () => { }) // 連向模擬的 User table - this.userController = createControllerProxy('../../controllers/userController', { User: this.UserMock }) + this.userController = createControllerProxy('../controllers/userController', { User: this.UserMock }) }) it(' GET /users/:id/edit ', async () => { @@ -127,7 +127,7 @@ describe('# R02', () => { ) // 連向模擬的 User table - this.userController = createControllerProxy('../../controllers/userController', { User: this.UserMock }) + this.userController = createControllerProxy('../controllers/userController', { User: this.UserMock }) }) it(' PUT /users/:id ', async () => { From e45367f2d4a0648f534bab260eee5080c624a7bf Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:50:30 +0800 Subject: [PATCH 013/101] add mockRequest / mockResponse --- helpers/unitTestHelpers.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index ea4cc7b1..35719e1a 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -79,7 +79,22 @@ const createControllerProxy = (path, model) => { return controller; } +const mockRequest = (query) => { + return { + ...query, + flash: sinon.spy(), + } +} +const mockResponse = () => { + return { + redirect: sinon.spy(), + render: sinon.spy(), + } +} + module.exports = { createModelMock, - createControllerProxy + createControllerProxy, + mockRequest, + mockResponse } \ No newline at end of file From d487f4afcdfd27e247aa57eef3a5caadb84c6a00 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:51:23 +0800 Subject: [PATCH 014/101] use new mockRequest / mockResponse --- tests/R01.test.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index f98a96ac..e9024d9e 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -4,19 +4,7 @@ const sinon = require('sinon') const should = chai.should() const app = require('../app') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - } -} +const { createModelMock, createControllerProxy, mockRequest, mockResponse } = require('../helpers/unitTestHelpers'); describe('# R01', () => { describe('登入測試: POST /signin', function(){ @@ -159,8 +147,6 @@ describe('# R01', () => { // 將假資料撈出,比對確認有成功修改到 const user = await this.UserMock.findOne({ where: { id: 1 } }) user.isAdmin.should.equal(true) - - done() }) }) }) From 73fc123d27ccec774163b66a9a3c1eca7fe59e42 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:57:12 +0800 Subject: [PATCH 015/101] require sinon --- helpers/unitTestHelpers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index 35719e1a..b6e47239 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -1,5 +1,6 @@ const SequelizeMock = require('sequelize-mock') const proxyquire = require('proxyquire') +const sinon = require('sinon') const dbMock = new SequelizeMock() From 5224b9a3e0866d314dd5346067c0de7f7a1fc25b Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:57:25 +0800 Subject: [PATCH 016/101] remove sinon --- tests/R01.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index e9024d9e..0a15875b 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -1,6 +1,5 @@ const chai = require('chai') const request = require('supertest') -const sinon = require('sinon') const should = chai.should() const app = require('../app') From 5d61a3029bd40bc0d0ae59f334e248e2a4c5b800 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:50:30 +0800 Subject: [PATCH 017/101] add mockRequest / mockResponse --- helpers/unitTestHelpers.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index ea4cc7b1..35719e1a 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -79,7 +79,22 @@ const createControllerProxy = (path, model) => { return controller; } +const mockRequest = (query) => { + return { + ...query, + flash: sinon.spy(), + } +} +const mockResponse = () => { + return { + redirect: sinon.spy(), + render: sinon.spy(), + } +} + module.exports = { createModelMock, - createControllerProxy + createControllerProxy, + mockRequest, + mockResponse } \ No newline at end of file From 51b22d50df8eff05fc26944bfc502d53151c7b76 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:51:23 +0800 Subject: [PATCH 018/101] use new mockRequest / mockResponse --- tests/R01.test.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index f98a96ac..e9024d9e 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -4,19 +4,7 @@ const sinon = require('sinon') const should = chai.should() const app = require('../app') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - } -} +const { createModelMock, createControllerProxy, mockRequest, mockResponse } = require('../helpers/unitTestHelpers'); describe('# R01', () => { describe('登入測試: POST /signin', function(){ @@ -159,8 +147,6 @@ describe('# R01', () => { // 將假資料撈出,比對確認有成功修改到 const user = await this.UserMock.findOne({ where: { id: 1 } }) user.isAdmin.should.equal(true) - - done() }) }) }) From eba6e760aa83e13ba046d6fafeb17560152d00e8 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:57:12 +0800 Subject: [PATCH 019/101] require sinon --- helpers/unitTestHelpers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index 35719e1a..b6e47239 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -1,5 +1,6 @@ const SequelizeMock = require('sequelize-mock') const proxyquire = require('proxyquire') +const sinon = require('sinon') const dbMock = new SequelizeMock() From 70db2a5a30afc5be1c5eaa83ffe6b71ced12d8dd Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:57:25 +0800 Subject: [PATCH 020/101] remove sinon --- tests/R01.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index e9024d9e..0a15875b 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -1,6 +1,5 @@ const chai = require('chai') const request = require('supertest') -const sinon = require('sinon') const should = chai.should() const app = require('../app') From 94b4d563a28a8ed36dabb695ffce20c94659f7ba Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:57:25 +0800 Subject: [PATCH 021/101] remove sinon --- tests/R01.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index f98a96ac..3d8c0e04 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -1,6 +1,5 @@ const chai = require('chai') const request = require('supertest') -const sinon = require('sinon') const should = chai.should() const app = require('../app') From 2d1863180f319ed2a536ee1f37facf0d90c5bfed Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:50:30 +0800 Subject: [PATCH 022/101] add mockRequest / mockResponse --- helpers/unitTestHelpers.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index ea4cc7b1..35719e1a 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -79,7 +79,22 @@ const createControllerProxy = (path, model) => { return controller; } +const mockRequest = (query) => { + return { + ...query, + flash: sinon.spy(), + } +} +const mockResponse = () => { + return { + redirect: sinon.spy(), + render: sinon.spy(), + } +} + module.exports = { createModelMock, - createControllerProxy + createControllerProxy, + mockRequest, + mockResponse } \ No newline at end of file From a79fdd0149d0e127598ef85d97d692ff0e04c558 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:51:23 +0800 Subject: [PATCH 023/101] use new mockRequest / mockResponse --- tests/R01.test.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index 3d8c0e04..0a15875b 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -3,19 +3,7 @@ const request = require('supertest') const should = chai.should() const app = require('../app') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - } -} +const { createModelMock, createControllerProxy, mockRequest, mockResponse } = require('../helpers/unitTestHelpers'); describe('# R01', () => { describe('登入測試: POST /signin', function(){ @@ -158,8 +146,6 @@ describe('# R01', () => { // 將假資料撈出,比對確認有成功修改到 const user = await this.UserMock.findOne({ where: { id: 1 } }) user.isAdmin.should.equal(true) - - done() }) }) }) From 7fef8c78760f41165f1ca6c0b7f884f73b862feb Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:57:12 +0800 Subject: [PATCH 024/101] require sinon --- helpers/unitTestHelpers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index 35719e1a..b6e47239 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -1,5 +1,6 @@ const SequelizeMock = require('sequelize-mock') const proxyquire = require('proxyquire') +const sinon = require('sinon') const dbMock = new SequelizeMock() From 9bf30ca0089c2c21723f40d14d75ee768d209c98 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 22:34:38 +0800 Subject: [PATCH 025/101] return [defaulvalue] when findall data empty --- helpers/unitTestHelpers.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index b6e47239..4a777f4c 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -33,6 +33,9 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(data.map(d => mockModel.build(d))) } else if (query === 'findAll') { // 回傳模擬資料 + if (!data) { + return mockModel.build([defaultValue]); + } return Promise.resolve( data ? data.map(d => mockModel.build(d)) : []) }else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 @@ -57,6 +60,9 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(mockModel.build(data)) } else if (query === 'findAll') { // 回傳模擬資料 + if (!data) { + return mockModel.build([defaultValue]); + } return Promise.resolve(data ? data.map(d => mockModel.build(d)) : []) } else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 From 05b87a2915b4d920a79e74797bd3a74574740c0f Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Tue, 2 Nov 2021 19:53:43 +0800 Subject: [PATCH 026/101] remove done param --- tests/R01.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index 0a15875b..2765ccfb 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -128,7 +128,7 @@ describe('# R01', () => { this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) - it(' PUT /admin/users/:id/toggleAdmin ', async (done) => { + it(' PUT /admin/users/:id/toggleAdmin ', async () => { // 模擬 request & response const req = mockRequest({ params: { id: 1 } }) // 帶入 params.id = 1,對 PUT /admin/users/1/toggleAdmin 發出請求 const res = mockResponse() From c014106ac7ed2244dbdf154ab97ba867fdfbe076 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Tue, 2 Nov 2021 19:53:43 +0800 Subject: [PATCH 027/101] remove done param --- tests/R01.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index 0a15875b..2765ccfb 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -128,7 +128,7 @@ describe('# R01', () => { this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) - it(' PUT /admin/users/:id/toggleAdmin ', async (done) => { + it(' PUT /admin/users/:id/toggleAdmin ', async () => { // 模擬 request & response const req = mockRequest({ params: { id: 1 } }) // 帶入 params.id = 1,對 PUT /admin/users/1/toggleAdmin 發出請求 const res = mockResponse() From 6eecc8ae14c26000f3a6cc22f2d0baa6b3df4dc3 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Tue, 2 Nov 2021 19:53:43 +0800 Subject: [PATCH 028/101] remove done param --- tests/R01.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/R01.test.js b/tests/R01.test.js index 0a15875b..2765ccfb 100644 --- a/tests/R01.test.js +++ b/tests/R01.test.js @@ -128,7 +128,7 @@ describe('# R01', () => { this.adminController = createControllerProxy('../controllers/adminController', { User: this.UserMock }) }) - it(' PUT /admin/users/:id/toggleAdmin ', async (done) => { + it(' PUT /admin/users/:id/toggleAdmin ', async () => { // 模擬 request & response const req = mockRequest({ params: { id: 1 } }) // 帶入 params.id = 1,對 PUT /admin/users/1/toggleAdmin 發出請求 const res = mockResponse() From a1cf9c3e517a11d3844a39377fe62f42ad2c3956 Mon Sep 17 00:00:00 2001 From: Carrot7712 Date: Wed, 3 Nov 2021 15:28:42 +0800 Subject: [PATCH 029/101] update readme config.json package.json --- README.md | 26 +- config/config.json | 14 +- package-lock.json | 2540 +------------------------------------------- package.json | 28 +- 4 files changed, 39 insertions(+), 2569 deletions(-) diff --git a/README.md b/README.md index e4cd70f1..9172af88 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ 1. Fork 2. git clone -3. 更改專案名稱 ## 初始化 ### Initialize @@ -16,14 +15,6 @@ npm install ``` create database forum; -create database forum_test; -``` - -### 切換環境 - -``` -export NODE_ENV=test # 切換到測試環境,如果在等號後加其他的字串,則會切到其他的環境 -echo $NODE_ENV # 印出目前使用的環境 ``` ### 執行測試 @@ -32,11 +23,11 @@ npm run test ``` ## 下載作業規格 -以 A17 為例 +以 R01 為例 ``` -git checkout -b A17 # 開新分支 -git merge origin/A17-test # 下載作業規格 +git checkout -b R01 # 開新分支 +git merge origin/R01-test # 下載作業規格 npm run test # 直到綠燈全亮 git add . @@ -46,11 +37,16 @@ git commit -m "...." ## 繳交作業 ``` -git push origin A17 # 上傳本地進度 +git push origin R01 # 上傳本地進度 ``` 接著改成到 GitHub 來發 PR。 ## 共用帳號 -請一律設定一個共用的 root user -root@example.com,登入密碼 12345678 +請一律設定下面 2 組帳號以利驗收: +* 第一組帳號有 admin 權限: + * email: root@example.com + * password: 12345678 +* 第二組帳號沒有 admin 權限: + * email: user1@example.com + * password: 12345678 \ No newline at end of file diff --git a/config/config.json b/config/config.json index 56636a1c..2b8be8e7 100644 --- a/config/config.json +++ b/config/config.json @@ -6,16 +6,12 @@ "host": "127.0.0.1", "dialect": "mysql" }, - "test": { + "production": { "username": "root", - "password": "password", - "database": "forum_test", + "password": null, + "database": "database_production", "host": "127.0.0.1", - "dialect": "mysql", - "logging": false - }, - "production": { - "use_env_variable": "CLEARDB_SILVER_URL" + "dialect": "mysql" }, "travis": { "username": "travis", @@ -24,4 +20,4 @@ "dialect": "mysql", "logging": false } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 7ebc04a3..bb00f848 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,2480 +1,8 @@ { "name": "forum-express-workspace", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "forum-express-workspace", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "chai": "^4.2.0", - "express": "^4.17.1", - "mocha": "^8.2.0", - "mysql2": "^2.2.5", - "sequelize": "^6.3.5", - "sequelize-cli": "^6.2.0", - "sinon": "^9.2.0", - "supertest": "^5.0.0" - }, - "devDependencies": { - "proxyquire": "^2.1.3", - "sequelize-mock": "^0.10.2" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dependencies": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.2.0.tgz", - "integrity": "sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw==", - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" - }, - "node_modules/@types/node": { - "version": "14.14.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.5.tgz", - "integrity": "sha512-H5Wn24s/ZOukBmDn03nnGTp18A60ny9AmCwnEcgJiTgSGsCO7k+NWP7zjCCbhlcnVCoI+co52dUAt9GMhOSULw==" - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "node_modules/anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "engines": { - "node": "*" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - }, - "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.2" - } - }, - "node_modules/cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "dependencies": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", - "engines": { - "node": ">=0.10" - } - }, - "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/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "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/dottie": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", - "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" - }, - "node_modules/editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "bin": { - "editorconfig": "bin/editorconfig" - } - }, - "node_modules/editorconfig/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/editorconfig/node_modules/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/editorconfig/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "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.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "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/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" - }, - "node_modules/fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" - }, - "node_modules/fill-keys": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/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/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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/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": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "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/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "deprecated": "\"Please update to latest v2.3 or v2.2\"", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "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/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" - }, - "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-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/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": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "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.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "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.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "deprecated": "Please update to ini >=1.3.6 to avoid a prototype pollution issue", - "engines": { - "node": "*" - } - }, - "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-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz", - "integrity": "sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" - }, - "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/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.13.0", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.13.0.tgz", - "integrity": "sha512-/Tbp1OVzZjbwzwJQFIlYLm9eWQ+3aYbBXLSaqb1mEJzhcQAfrqMMQYtjb6io+U6KpD0ID4F+Id3/xcjH3l/sqA==", - "dependencies": { - "config-chain": "^1.1.12", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "mkdirp": "^1.0.4", - "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" - } - }, - "node_modules/js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "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.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==" - }, - "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.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "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": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "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/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "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.14", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } - }, - "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/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.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dependencies": { - "mime-db": "1.44.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/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.0.tgz", - "integrity": "sha512-lEWEMq2LMfNJMKeuEwb5UELi+OgFDollXaytR5ggQcHpzG3NP/R7rvixAvF+9/lLsTWhWG+4yD2M70GsM06nxw==", - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.4.3", - "debug": "4.2.0", - "diff": "4.0.2", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.14.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.2", - "nanoid": "3.1.12", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "7.2.0", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.2", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 10.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/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/mocha/node_modules/p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/module-not-found-error": { - "version": "1.0.1", - "resolved": "http://npm.ooapi.com:4873/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, - "node_modules/moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", - "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", - "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": "2.2.5", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.2.5.tgz", - "integrity": "sha512-XRqPNxcZTpmFdXbJqb+/CtYVLCx14x1RTeNMD4954L331APu75IC74GDqnZMEt1kwaXy6TySo55rF2F3YJS78g==", - "dependencies": { - "denque": "^1.4.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.2", - "long": "^4.0.0", - "lru-cache": "^6.0.0", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "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/nanoid": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", - "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || >=13.7" - } - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "node_modules/nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", - "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/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/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "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/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/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.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "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.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "engines": { - "node": "*" - } - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxyquire": { - "version": "2.1.3", - "resolved": "http://npm.ooapi.com:4873/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.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "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.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "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.18.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", - "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", - "dependencies": { - "is-core-module": "^2.0.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/retry-as-promised": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", - "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", - "dependencies": { - "any-promise": "^1.3.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "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.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/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/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.3.5", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.5.tgz", - "integrity": "sha512-MiwiPkYSA8NWttRKAXdU9h0TxP6HAc1fl7qZmMO/VQqQOND83G4nZLXd0kWILtAoT9cxtZgFqeb/MPYgEeXwsw==", - "dependencies": { - "debug": "^4.1.1", - "dottie": "^2.0.0", - "inflection": "1.12.0", - "lodash": "^4.17.15", - "moment": "^2.26.0", - "moment-timezone": "^0.5.31", - "retry-as-promised": "^3.2.0", - "semver": "^7.3.2", - "sequelize-pool": "^6.0.0", - "toposort-class": "^1.0.1", - "uuid": "^8.1.0", - "validator": "^10.11.0", - "wkx": "^0.5.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependenciesMeta": { - "mariadb": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-hstore": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "tedious": { - "optional": true - } - } - }, - "node_modules/sequelize-cli": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", - "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", - "dependencies": { - "cli-color": "^1.4.0", - "fs-extra": "^7.0.1", - "js-beautify": "^1.8.8", - "lodash": "^4.17.5", - "resolve": "^1.5.0", - "umzug": "^2.3.0", - "yargs": "^13.1.0" - }, - "bin": { - "sequelize": "lib/sequelize", - "sequelize-cli": "lib/sequelize" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/sequelize-mock": { - "version": "0.10.2", - "resolved": "http://npm.ooapi.com:4873/sequelize-mock/-/sequelize-mock-0.10.2.tgz", - "integrity": "sha1-GdOXHM2utbhkFwwkznkqinHxRL0=", - "dev": true, - "dependencies": { - "bluebird": "^3.4.6", - "inflection": "^1.10.0", - "lodash": "^4.16.4" - } - }, - "node_modules/sequelize-pool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", - "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/sequelize/node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/sequelize/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "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.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "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": "9.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.0.tgz", - "integrity": "sha512-eSNXz1XMcGEMHw08NJXSyTHIu6qTCOiN8x9ODACmZpNQpr0aXTBXBnI4xTzQzR+TEpOmLiKowGf9flCuKIzsbw==", - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.2.0", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "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.2", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz", - "integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==", - "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.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string_decoder/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/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/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/strip-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superagent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", - "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.2", - "methods": "^1.1.2", - "mime": "^2.4.6", - "qs": "^6.9.4", - "readable-stream": "^3.6.0", - "semver": "^7.3.2" - }, - "engines": { - "node": ">= 7.0.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/superagent/node_modules/mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/superagent/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/superagent/node_modules/qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/supertest": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-5.0.0.tgz", - "integrity": "sha512-2JAWpPrUOZF4hHH5ZTCN2xjKXvJS3AEwPNXl0HUseHsfcXFvMy9kcsufIHCNAmQ5hlGCvgeAqaR5PBEouN3hlQ==", - "dependencies": { - "methods": "1.1.2", - "superagent": "6.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "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/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/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=" - }, - "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.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validator": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", - "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", - "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": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "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/wide-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wkx": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/workerpool": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", - "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==" - }, - "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/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.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, "dependencies": { "@sinonjs/commons": { "version": "1.8.1", @@ -3053,16 +581,6 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, - "fill-keys": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - } - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3304,12 +822,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, - "is-object": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true - }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -3563,12 +1075,6 @@ } } }, - "module-not-found-error": { - "version": "1.0.1", - "resolved": "http://npm.ooapi.com:4873/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, "moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", @@ -3772,17 +1278,6 @@ "ipaddr.js": "1.9.1" } }, - "proxyquire": { - "version": "2.1.3", - "resolved": "http://npm.ooapi.com:4873/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", - "dev": true, - "requires": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" - } - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -3958,17 +1453,6 @@ "yargs": "^13.1.0" } }, - "sequelize-mock": { - "version": "0.10.2", - "resolved": "http://npm.ooapi.com:4873/sequelize-mock/-/sequelize-mock-0.10.2.tgz", - "integrity": "sha1-GdOXHM2utbhkFwwkznkqinHxRL0=", - "dev": true, - "requires": { - "bluebird": "^3.4.6", - "inflection": "^1.10.0", - "lodash": "^4.16.4" - } - }, "sequelize-pool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", @@ -4037,6 +1521,16 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "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" + } + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4052,16 +1546,6 @@ } } }, - "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", @@ -4364,4 +1848,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index c25bd055..5f6f1d0f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { - "name": "forum-express-workspace", - "version": "1.0.0", - "description": "", + "name": "forum-express-grading", + "version": "2.0.0", "main": "_helpers.js", "scripts": { "start": "node app.js", @@ -10,26 +9,21 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/v123582/forum-express-workspace.git" + "url": "git+https://github.com/ALPHACamp/forum-express-grading.git" }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/v123582/forum-express-workspace/issues" - }, - "homepage": "https://github.com/v123582/forum-express-workspace#readme", "dependencies": { - "chai": "^4.2.0", "express": "^4.17.1", - "mocha": "^8.2.0", "mysql2": "^2.2.5", + "nodemon": "^2.0.12", "sequelize": "^6.3.5", - "sequelize-cli": "^6.2.0", - "sinon": "^9.2.0", - "supertest": "^5.0.0" + "sequelize-cli": "^6.2.0" }, "devDependencies": { + "chai": "^4.2.0", + "mocha": "^8.2.0", "proxyquire": "^2.1.3", - "sequelize-mock": "^0.10.2" + "sequelize-mock": "^0.10.2", + "sinon": "^9.2.0", + "supertest": "^5.0.0" } -} +} \ No newline at end of file From 5e1573a5ba7da44df7530b009b8ed565a552a62a Mon Sep 17 00:00:00 2001 From: Serena Tseng <51045074+Carrot7712@users.noreply.github.com> Date: Sat, 6 Nov 2021 00:14:56 +0800 Subject: [PATCH 030/101] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9635c20c..fdf50b79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,9 +11,9 @@ env: # 在 install 前執行的指令 before_install: - - mysql -e 'CREATE DATABASE IF NOT EXISTS forum_test default character set utf8mb4 collate utf8mb4_unicode_ci;' + - mysql -e 'CREATE DATABASE IF NOT EXISTS forum default character set utf8mb4 collate utf8mb4_unicode_ci;' - npm install sequelize-cli -g # 在執行測試之前的指令 before_script: - - sequelize db:migrate \ No newline at end of file + - sequelize db:migrate From c71da4437577e06e72e85113c9ae4eb5726a3f6d Mon Sep 17 00:00:00 2001 From: Serena Tseng <51045074+Carrot7712@users.noreply.github.com> Date: Sat, 6 Nov 2021 00:29:51 +0800 Subject: [PATCH 031/101] Update .travis.yml --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fdf50b79..f08c1b5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "10" + - "14" services: - mysql @@ -16,4 +16,5 @@ before_install: # 在執行測試之前的指令 before_script: - - sequelize db:migrate + - sequelize db:migrate + - sequelize db:seed:all From 1da8f648fee9345d65ebbf74d734448d28d7f869 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:52:15 +0800 Subject: [PATCH 032/101] R02 use new mockRequest / mockResponse --- tests/R02.test.js | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/tests/R02.test.js b/tests/R02.test.js index 5b7cadb2..6463e997 100644 --- a/tests/R02.test.js +++ b/tests/R02.test.js @@ -3,20 +3,8 @@ const request = require('supertest') const sinon = require('sinon') const should = chai.should() -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} +const { createModelMock, createControllerProxy, mockRequest, mockResponse } = require('../helpers/unitTestHelpers'); + describe('# R02', () => { describe('# R02: 建立 User Profile', function () { context('# [瀏覽 Profile]', () => { From dcc8f0ea6ecedcd515f536bd5283b7e6bdced693 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 8 Nov 2021 01:15:19 +0800 Subject: [PATCH 033/101] add helper ref --- tests/R02.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/R02.test.js b/tests/R02.test.js index 6463e997..26c927b3 100644 --- a/tests/R02.test.js +++ b/tests/R02.test.js @@ -3,6 +3,8 @@ const request = require('supertest') const sinon = require('sinon') const should = chai.should() +const helpers = require('../_helpers'); + const { createModelMock, createControllerProxy, mockRequest, mockResponse } = require('../helpers/unitTestHelpers'); describe('# R02', () => { From d54a7fd60d9ea2c09a52c8b690ad4e42c89d5379 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 1 Nov 2021 21:52:15 +0800 Subject: [PATCH 034/101] R02 use new mockRequest / mockResponse --- tests/R02.test.js | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/tests/R02.test.js b/tests/R02.test.js index 5b7cadb2..6463e997 100644 --- a/tests/R02.test.js +++ b/tests/R02.test.js @@ -3,20 +3,8 @@ const request = require('supertest') const sinon = require('sinon') const should = chai.should() -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} +const { createModelMock, createControllerProxy, mockRequest, mockResponse } = require('../helpers/unitTestHelpers'); + describe('# R02', () => { describe('# R02: 建立 User Profile', function () { context('# [瀏覽 Profile]', () => { From dde5d1d2e63bdb7e3ce4ead51f43da070411cdd3 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 8 Nov 2021 01:15:19 +0800 Subject: [PATCH 035/101] add helper ref --- tests/R02.test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/R02.test.js b/tests/R02.test.js index 6463e997..26c927b3 100644 --- a/tests/R02.test.js +++ b/tests/R02.test.js @@ -3,6 +3,8 @@ const request = require('supertest') const sinon = require('sinon') const should = chai.should() +const helpers = require('../_helpers'); + const { createModelMock, createControllerProxy, mockRequest, mockResponse } = require('../helpers/unitTestHelpers'); describe('# R02', () => { From 049790e9f5dca0d19b8d23a59f7baed7f9df3667 Mon Sep 17 00:00:00 2001 From: Amber Yan Date: Mon, 8 Nov 2021 01:52:24 +0800 Subject: [PATCH 036/101] use new mockRequest, mockResponse --- tests/R03.test.js | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/tests/R03.test.js b/tests/R03.test.js index bc7d1ade..f415be50 100644 --- a/tests/R03.test.js +++ b/tests/R03.test.js @@ -4,20 +4,7 @@ const sinon = require('sinon') const should = chai.should() const helpers = require('../_helpers') -const { createModelMock, createControllerProxy } = require('../helpers/unitTestHelpers'); - -const mockRequest = (query) => { - return { - ...query, - flash: sinon.spy(), - } -} -const mockResponse = () => { - return { - redirect: sinon.spy(), - render: sinon.spy(), - } -} +const { createModelMock, createControllerProxy, mockRequest, mockResponse } = require('../helpers/unitTestHelpers'); describe('# R03: 餐廳資訊整理:Dashboard', function () { context('# [Q1: Dashboard - 1 - controller / view / route]', () => { From 72b97383c0e5c062469191ad96ee0b4ac1911861 Mon Sep 17 00:00:00 2001 From: Carrot7712 Date: Wed, 3 Nov 2021 15:28:42 +0800 Subject: [PATCH 037/101] update readme config.json package.json --- README.md | 26 +- config/config.json | 14 +- package-lock.json | 2540 +------------------------------------------- package.json | 28 +- 4 files changed, 39 insertions(+), 2569 deletions(-) diff --git a/README.md b/README.md index e4cd70f1..9172af88 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ 1. Fork 2. git clone -3. 更改專案名稱 ## 初始化 ### Initialize @@ -16,14 +15,6 @@ npm install ``` create database forum; -create database forum_test; -``` - -### 切換環境 - -``` -export NODE_ENV=test # 切換到測試環境,如果在等號後加其他的字串,則會切到其他的環境 -echo $NODE_ENV # 印出目前使用的環境 ``` ### 執行測試 @@ -32,11 +23,11 @@ npm run test ``` ## 下載作業規格 -以 A17 為例 +以 R01 為例 ``` -git checkout -b A17 # 開新分支 -git merge origin/A17-test # 下載作業規格 +git checkout -b R01 # 開新分支 +git merge origin/R01-test # 下載作業規格 npm run test # 直到綠燈全亮 git add . @@ -46,11 +37,16 @@ git commit -m "...." ## 繳交作業 ``` -git push origin A17 # 上傳本地進度 +git push origin R01 # 上傳本地進度 ``` 接著改成到 GitHub 來發 PR。 ## 共用帳號 -請一律設定一個共用的 root user -root@example.com,登入密碼 12345678 +請一律設定下面 2 組帳號以利驗收: +* 第一組帳號有 admin 權限: + * email: root@example.com + * password: 12345678 +* 第二組帳號沒有 admin 權限: + * email: user1@example.com + * password: 12345678 \ No newline at end of file diff --git a/config/config.json b/config/config.json index 56636a1c..2b8be8e7 100644 --- a/config/config.json +++ b/config/config.json @@ -6,16 +6,12 @@ "host": "127.0.0.1", "dialect": "mysql" }, - "test": { + "production": { "username": "root", - "password": "password", - "database": "forum_test", + "password": null, + "database": "database_production", "host": "127.0.0.1", - "dialect": "mysql", - "logging": false - }, - "production": { - "use_env_variable": "CLEARDB_SILVER_URL" + "dialect": "mysql" }, "travis": { "username": "travis", @@ -24,4 +20,4 @@ "dialect": "mysql", "logging": false } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 7ebc04a3..bb00f848 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,2480 +1,8 @@ { "name": "forum-express-workspace", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "forum-express-workspace", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "chai": "^4.2.0", - "express": "^4.17.1", - "mocha": "^8.2.0", - "mysql2": "^2.2.5", - "sequelize": "^6.3.5", - "sequelize-cli": "^6.2.0", - "sinon": "^9.2.0", - "supertest": "^5.0.0" - }, - "devDependencies": { - "proxyquire": "^2.1.3", - "sequelize-mock": "^0.10.2" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dependencies": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.2.0.tgz", - "integrity": "sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw==", - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" - }, - "node_modules/@types/node": { - "version": "14.14.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.5.tgz", - "integrity": "sha512-H5Wn24s/ZOukBmDn03nnGTp18A60ny9AmCwnEcgJiTgSGsCO7k+NWP7zjCCbhlcnVCoI+co52dUAt9GMhOSULw==" - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "node_modules/anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "engines": { - "node": "*" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - }, - "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.2" - } - }, - "node_modules/cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "dependencies": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", - "engines": { - "node": ">=0.10" - } - }, - "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/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "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/dottie": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", - "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" - }, - "node_modules/editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "bin": { - "editorconfig": "bin/editorconfig" - } - }, - "node_modules/editorconfig/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/editorconfig/node_modules/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/editorconfig/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "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.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "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/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" - }, - "node_modules/fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" - }, - "node_modules/fill-keys": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/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/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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/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": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "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/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "deprecated": "\"Please update to latest v2.3 or v2.2\"", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "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/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" - }, - "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-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/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": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "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.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "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.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "deprecated": "Please update to ini >=1.3.6 to avoid a prototype pollution issue", - "engines": { - "node": "*" - } - }, - "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-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz", - "integrity": "sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" - }, - "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/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.13.0", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.13.0.tgz", - "integrity": "sha512-/Tbp1OVzZjbwzwJQFIlYLm9eWQ+3aYbBXLSaqb1mEJzhcQAfrqMMQYtjb6io+U6KpD0ID4F+Id3/xcjH3l/sqA==", - "dependencies": { - "config-chain": "^1.1.12", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "mkdirp": "^1.0.4", - "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" - } - }, - "node_modules/js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "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.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==" - }, - "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.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "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": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "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/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "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.14", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } - }, - "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/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.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dependencies": { - "mime-db": "1.44.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/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.0.tgz", - "integrity": "sha512-lEWEMq2LMfNJMKeuEwb5UELi+OgFDollXaytR5ggQcHpzG3NP/R7rvixAvF+9/lLsTWhWG+4yD2M70GsM06nxw==", - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.4.3", - "debug": "4.2.0", - "diff": "4.0.2", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.14.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.2", - "nanoid": "3.1.12", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "7.2.0", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.2", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 10.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/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/mocha/node_modules/p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/module-not-found-error": { - "version": "1.0.1", - "resolved": "http://npm.ooapi.com:4873/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, - "node_modules/moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", - "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", - "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": "2.2.5", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.2.5.tgz", - "integrity": "sha512-XRqPNxcZTpmFdXbJqb+/CtYVLCx14x1RTeNMD4954L331APu75IC74GDqnZMEt1kwaXy6TySo55rF2F3YJS78g==", - "dependencies": { - "denque": "^1.4.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.2", - "long": "^4.0.0", - "lru-cache": "^6.0.0", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "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/nanoid": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", - "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || >=13.7" - } - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "node_modules/nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", - "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/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/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "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/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/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.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "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.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "engines": { - "node": "*" - } - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxyquire": { - "version": "2.1.3", - "resolved": "http://npm.ooapi.com:4873/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.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "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.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "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.18.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", - "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", - "dependencies": { - "is-core-module": "^2.0.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/retry-as-promised": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", - "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", - "dependencies": { - "any-promise": "^1.3.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "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.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/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/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.3.5", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.5.tgz", - "integrity": "sha512-MiwiPkYSA8NWttRKAXdU9h0TxP6HAc1fl7qZmMO/VQqQOND83G4nZLXd0kWILtAoT9cxtZgFqeb/MPYgEeXwsw==", - "dependencies": { - "debug": "^4.1.1", - "dottie": "^2.0.0", - "inflection": "1.12.0", - "lodash": "^4.17.15", - "moment": "^2.26.0", - "moment-timezone": "^0.5.31", - "retry-as-promised": "^3.2.0", - "semver": "^7.3.2", - "sequelize-pool": "^6.0.0", - "toposort-class": "^1.0.1", - "uuid": "^8.1.0", - "validator": "^10.11.0", - "wkx": "^0.5.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependenciesMeta": { - "mariadb": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-hstore": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "tedious": { - "optional": true - } - } - }, - "node_modules/sequelize-cli": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", - "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", - "dependencies": { - "cli-color": "^1.4.0", - "fs-extra": "^7.0.1", - "js-beautify": "^1.8.8", - "lodash": "^4.17.5", - "resolve": "^1.5.0", - "umzug": "^2.3.0", - "yargs": "^13.1.0" - }, - "bin": { - "sequelize": "lib/sequelize", - "sequelize-cli": "lib/sequelize" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/sequelize-mock": { - "version": "0.10.2", - "resolved": "http://npm.ooapi.com:4873/sequelize-mock/-/sequelize-mock-0.10.2.tgz", - "integrity": "sha1-GdOXHM2utbhkFwwkznkqinHxRL0=", - "dev": true, - "dependencies": { - "bluebird": "^3.4.6", - "inflection": "^1.10.0", - "lodash": "^4.16.4" - } - }, - "node_modules/sequelize-pool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", - "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/sequelize/node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/sequelize/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "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.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "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": "9.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.0.tgz", - "integrity": "sha512-eSNXz1XMcGEMHw08NJXSyTHIu6qTCOiN8x9ODACmZpNQpr0aXTBXBnI4xTzQzR+TEpOmLiKowGf9flCuKIzsbw==", - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.2.0", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "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.2", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz", - "integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==", - "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.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string_decoder/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/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/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/strip-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superagent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", - "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.2", - "methods": "^1.1.2", - "mime": "^2.4.6", - "qs": "^6.9.4", - "readable-stream": "^3.6.0", - "semver": "^7.3.2" - }, - "engines": { - "node": ">= 7.0.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/superagent/node_modules/mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/superagent/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/superagent/node_modules/qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/supertest": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-5.0.0.tgz", - "integrity": "sha512-2JAWpPrUOZF4hHH5ZTCN2xjKXvJS3AEwPNXl0HUseHsfcXFvMy9kcsufIHCNAmQ5hlGCvgeAqaR5PBEouN3hlQ==", - "dependencies": { - "methods": "1.1.2", - "superagent": "6.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "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/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/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=" - }, - "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.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validator": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", - "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", - "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": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "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/wide-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wkx": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/workerpool": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", - "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==" - }, - "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/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.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, "dependencies": { "@sinonjs/commons": { "version": "1.8.1", @@ -3053,16 +581,6 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, - "fill-keys": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - } - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3304,12 +822,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, - "is-object": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true - }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -3563,12 +1075,6 @@ } } }, - "module-not-found-error": { - "version": "1.0.1", - "resolved": "http://npm.ooapi.com:4873/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, "moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", @@ -3772,17 +1278,6 @@ "ipaddr.js": "1.9.1" } }, - "proxyquire": { - "version": "2.1.3", - "resolved": "http://npm.ooapi.com:4873/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", - "dev": true, - "requires": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" - } - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -3958,17 +1453,6 @@ "yargs": "^13.1.0" } }, - "sequelize-mock": { - "version": "0.10.2", - "resolved": "http://npm.ooapi.com:4873/sequelize-mock/-/sequelize-mock-0.10.2.tgz", - "integrity": "sha1-GdOXHM2utbhkFwwkznkqinHxRL0=", - "dev": true, - "requires": { - "bluebird": "^3.4.6", - "inflection": "^1.10.0", - "lodash": "^4.16.4" - } - }, "sequelize-pool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", @@ -4037,6 +1521,16 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "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" + } + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4052,16 +1546,6 @@ } } }, - "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", @@ -4364,4 +1848,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index c25bd055..5f6f1d0f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { - "name": "forum-express-workspace", - "version": "1.0.0", - "description": "", + "name": "forum-express-grading", + "version": "2.0.0", "main": "_helpers.js", "scripts": { "start": "node app.js", @@ -10,26 +9,21 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/v123582/forum-express-workspace.git" + "url": "git+https://github.com/ALPHACamp/forum-express-grading.git" }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/v123582/forum-express-workspace/issues" - }, - "homepage": "https://github.com/v123582/forum-express-workspace#readme", "dependencies": { - "chai": "^4.2.0", "express": "^4.17.1", - "mocha": "^8.2.0", "mysql2": "^2.2.5", + "nodemon": "^2.0.12", "sequelize": "^6.3.5", - "sequelize-cli": "^6.2.0", - "sinon": "^9.2.0", - "supertest": "^5.0.0" + "sequelize-cli": "^6.2.0" }, "devDependencies": { + "chai": "^4.2.0", + "mocha": "^8.2.0", "proxyquire": "^2.1.3", - "sequelize-mock": "^0.10.2" + "sequelize-mock": "^0.10.2", + "sinon": "^9.2.0", + "supertest": "^5.0.0" } -} +} \ No newline at end of file From 8c88719874fe6693bfbd7888c51aa3b6fe61ce2e Mon Sep 17 00:00:00 2001 From: Serena Tseng <51045074+Carrot7712@users.noreply.github.com> Date: Sat, 6 Nov 2021 00:14:56 +0800 Subject: [PATCH 038/101] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9635c20c..fdf50b79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,9 +11,9 @@ env: # 在 install 前執行的指令 before_install: - - mysql -e 'CREATE DATABASE IF NOT EXISTS forum_test default character set utf8mb4 collate utf8mb4_unicode_ci;' + - mysql -e 'CREATE DATABASE IF NOT EXISTS forum default character set utf8mb4 collate utf8mb4_unicode_ci;' - npm install sequelize-cli -g # 在執行測試之前的指令 before_script: - - sequelize db:migrate \ No newline at end of file + - sequelize db:migrate From ec2c6dfa2008eeafedabd2335ae7b81a08fdb0b8 Mon Sep 17 00:00:00 2001 From: Serena Tseng <51045074+Carrot7712@users.noreply.github.com> Date: Sat, 6 Nov 2021 00:29:51 +0800 Subject: [PATCH 039/101] Update .travis.yml --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fdf50b79..f08c1b5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "10" + - "14" services: - mysql @@ -16,4 +16,5 @@ before_install: # 在執行測試之前的指令 before_script: - - sequelize db:migrate + - sequelize db:migrate + - sequelize db:seed:all From 80d4dd130931d520be0ebe7b31e772c9bf6dbf04 Mon Sep 17 00:00:00 2001 From: Carrot7712 Date: Wed, 3 Nov 2021 15:28:42 +0800 Subject: [PATCH 040/101] update readme config.json package.json --- README.md | 26 +- config/config.json | 14 +- package-lock.json | 2540 +------------------------------------------- package.json | 28 +- 4 files changed, 39 insertions(+), 2569 deletions(-) diff --git a/README.md b/README.md index e4cd70f1..9172af88 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ 1. Fork 2. git clone -3. 更改專案名稱 ## 初始化 ### Initialize @@ -16,14 +15,6 @@ npm install ``` create database forum; -create database forum_test; -``` - -### 切換環境 - -``` -export NODE_ENV=test # 切換到測試環境,如果在等號後加其他的字串,則會切到其他的環境 -echo $NODE_ENV # 印出目前使用的環境 ``` ### 執行測試 @@ -32,11 +23,11 @@ npm run test ``` ## 下載作業規格 -以 A17 為例 +以 R01 為例 ``` -git checkout -b A17 # 開新分支 -git merge origin/A17-test # 下載作業規格 +git checkout -b R01 # 開新分支 +git merge origin/R01-test # 下載作業規格 npm run test # 直到綠燈全亮 git add . @@ -46,11 +37,16 @@ git commit -m "...." ## 繳交作業 ``` -git push origin A17 # 上傳本地進度 +git push origin R01 # 上傳本地進度 ``` 接著改成到 GitHub 來發 PR。 ## 共用帳號 -請一律設定一個共用的 root user -root@example.com,登入密碼 12345678 +請一律設定下面 2 組帳號以利驗收: +* 第一組帳號有 admin 權限: + * email: root@example.com + * password: 12345678 +* 第二組帳號沒有 admin 權限: + * email: user1@example.com + * password: 12345678 \ No newline at end of file diff --git a/config/config.json b/config/config.json index 56636a1c..2b8be8e7 100644 --- a/config/config.json +++ b/config/config.json @@ -6,16 +6,12 @@ "host": "127.0.0.1", "dialect": "mysql" }, - "test": { + "production": { "username": "root", - "password": "password", - "database": "forum_test", + "password": null, + "database": "database_production", "host": "127.0.0.1", - "dialect": "mysql", - "logging": false - }, - "production": { - "use_env_variable": "CLEARDB_SILVER_URL" + "dialect": "mysql" }, "travis": { "username": "travis", @@ -24,4 +20,4 @@ "dialect": "mysql", "logging": false } -} \ No newline at end of file +} diff --git a/package-lock.json b/package-lock.json index 7ebc04a3..bb00f848 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,2480 +1,8 @@ { "name": "forum-express-workspace", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "forum-express-workspace", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "chai": "^4.2.0", - "express": "^4.17.1", - "mocha": "^8.2.0", - "mysql2": "^2.2.5", - "sequelize": "^6.3.5", - "sequelize-cli": "^6.2.0", - "sinon": "^9.2.0", - "supertest": "^5.0.0" - }, - "devDependencies": { - "proxyquire": "^2.1.3", - "sequelize-mock": "^0.10.2" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dependencies": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.2.0.tgz", - "integrity": "sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw==", - "dependencies": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==" - }, - "node_modules/@types/node": { - "version": "14.14.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.5.tgz", - "integrity": "sha512-H5Wn24s/ZOukBmDn03nnGTp18A60ny9AmCwnEcgJiTgSGsCO7k+NWP7zjCCbhlcnVCoI+co52dUAt9GMhOSULw==" - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, - "node_modules/anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "engines": { - "node": "*" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dependencies": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - }, - "node_modules/bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.2" - } - }, - "node_modules/cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "dependencies": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "node_modules/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" - }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", - "engines": { - "node": ">=0.10" - } - }, - "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/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "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/dottie": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", - "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" - }, - "node_modules/editorconfig": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", - "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", - "dependencies": { - "commander": "^2.19.0", - "lru-cache": "^4.1.5", - "semver": "^5.6.0", - "sigmund": "^1.0.1" - }, - "bin": { - "editorconfig": "bin/editorconfig" - } - }, - "node_modules/editorconfig/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/editorconfig/node_modules/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/editorconfig/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/es5-ext": { - "version": "0.10.53", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", - "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", - "dependencies": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.3", - "next-tick": "~1.0.0" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dependencies": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "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.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "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/ext": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", - "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", - "dependencies": { - "type": "^2.0.0" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", - "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" - }, - "node_modules/fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" - }, - "node_modules/fill-keys": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/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/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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/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": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/form-data": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", - "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "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/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "deprecated": "\"Please update to latest v2.3 or v2.2\"", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "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/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" - }, - "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-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/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": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "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.12.0", - "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", - "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=", - "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.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "deprecated": "Please update to ini >=1.3.6 to avoid a prototype pollution issue", - "engines": { - "node": "*" - } - }, - "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-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz", - "integrity": "sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "engines": { - "node": ">=4" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-object": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" - }, - "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/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.13.0", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.13.0.tgz", - "integrity": "sha512-/Tbp1OVzZjbwzwJQFIlYLm9eWQ+3aYbBXLSaqb1mEJzhcQAfrqMMQYtjb6io+U6KpD0ID4F+Id3/xcjH3l/sqA==", - "dependencies": { - "config-chain": "^1.1.12", - "editorconfig": "^0.15.3", - "glob": "^7.1.3", - "mkdirp": "^1.0.4", - "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" - } - }, - "node_modules/js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "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.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==" - }, - "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.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "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": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "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/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "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.14", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } - }, - "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/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.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dependencies": { - "mime-db": "1.44.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/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.0.tgz", - "integrity": "sha512-lEWEMq2LMfNJMKeuEwb5UELi+OgFDollXaytR5ggQcHpzG3NP/R7rvixAvF+9/lLsTWhWG+4yD2M70GsM06nxw==", - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.4.3", - "debug": "4.2.0", - "diff": "4.0.2", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.14.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.2", - "nanoid": "3.1.12", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "7.2.0", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.2", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 10.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/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/mocha/node_modules/p-limit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", - "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/module-not-found-error": { - "version": "1.0.1", - "resolved": "http://npm.ooapi.com:4873/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, - "node_modules/moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", - "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", - "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": "2.2.5", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.2.5.tgz", - "integrity": "sha512-XRqPNxcZTpmFdXbJqb+/CtYVLCx14x1RTeNMD4954L331APu75IC74GDqnZMEt1kwaXy6TySo55rF2F3YJS78g==", - "dependencies": { - "denque": "^1.4.1", - "generate-function": "^2.3.1", - "iconv-lite": "^0.6.2", - "long": "^4.0.0", - "lru-cache": "^6.0.0", - "named-placeholders": "^1.1.2", - "seq-queue": "^0.0.5", - "sqlstring": "^2.3.2" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/mysql2/node_modules/iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "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/nanoid": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", - "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || >=13.7" - } - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/next-tick": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" - }, - "node_modules/nise": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", - "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", - "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/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/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "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/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/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.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "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.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "engines": { - "node": "*" - } - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "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.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "dependencies": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxyquire": { - "version": "2.1.3", - "resolved": "http://npm.ooapi.com:4873/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.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "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.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dependencies": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "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.18.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", - "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", - "dependencies": { - "is-core-module": "^2.0.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/retry-as-promised": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", - "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", - "dependencies": { - "any-promise": "^1.3.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "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.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/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/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.3.5", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.5.tgz", - "integrity": "sha512-MiwiPkYSA8NWttRKAXdU9h0TxP6HAc1fl7qZmMO/VQqQOND83G4nZLXd0kWILtAoT9cxtZgFqeb/MPYgEeXwsw==", - "dependencies": { - "debug": "^4.1.1", - "dottie": "^2.0.0", - "inflection": "1.12.0", - "lodash": "^4.17.15", - "moment": "^2.26.0", - "moment-timezone": "^0.5.31", - "retry-as-promised": "^3.2.0", - "semver": "^7.3.2", - "sequelize-pool": "^6.0.0", - "toposort-class": "^1.0.1", - "uuid": "^8.1.0", - "validator": "^10.11.0", - "wkx": "^0.5.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependenciesMeta": { - "mariadb": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-hstore": { - "optional": true - }, - "sqlite3": { - "optional": true - }, - "tedious": { - "optional": true - } - } - }, - "node_modules/sequelize-cli": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-6.2.0.tgz", - "integrity": "sha512-6WQ2x91hg30dUn66mXHnzvHATZ4pyI1GHSNbS/TNN/vRR4BLRSLijadeMgC8zqmKDsL0VqzVVopJWfJakuP++Q==", - "dependencies": { - "cli-color": "^1.4.0", - "fs-extra": "^7.0.1", - "js-beautify": "^1.8.8", - "lodash": "^4.17.5", - "resolve": "^1.5.0", - "umzug": "^2.3.0", - "yargs": "^13.1.0" - }, - "bin": { - "sequelize": "lib/sequelize", - "sequelize-cli": "lib/sequelize" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/sequelize-mock": { - "version": "0.10.2", - "resolved": "http://npm.ooapi.com:4873/sequelize-mock/-/sequelize-mock-0.10.2.tgz", - "integrity": "sha1-GdOXHM2utbhkFwwkznkqinHxRL0=", - "dev": true, - "dependencies": { - "bluebird": "^3.4.6", - "inflection": "^1.10.0", - "lodash": "^4.16.4" - } - }, - "node_modules/sequelize-pool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", - "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/sequelize/node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/sequelize/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "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.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "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": "9.2.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.0.tgz", - "integrity": "sha512-eSNXz1XMcGEMHw08NJXSyTHIu6qTCOiN8x9ODACmZpNQpr0aXTBXBnI4xTzQzR+TEpOmLiKowGf9flCuKIzsbw==", - "dependencies": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.2.0", - "diff": "^4.0.2", - "nise": "^4.0.4", - "supports-color": "^7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "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.2", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz", - "integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==", - "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.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string_decoder/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/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/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/strip-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superagent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", - "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.2", - "methods": "^1.1.2", - "mime": "^2.4.6", - "qs": "^6.9.4", - "readable-stream": "^3.6.0", - "semver": "^7.3.2" - }, - "engines": { - "node": ">= 7.0.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "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.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/superagent/node_modules/mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/superagent/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/superagent/node_modules/qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/supertest": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-5.0.0.tgz", - "integrity": "sha512-2JAWpPrUOZF4hHH5ZTCN2xjKXvJS3AEwPNXl0HUseHsfcXFvMy9kcsufIHCNAmQ5hlGCvgeAqaR5PBEouN3hlQ==", - "dependencies": { - "methods": "1.1.2", - "superagent": "6.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "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/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/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=" - }, - "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.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/validator": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", - "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", - "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": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "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/wide-align/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wkx": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", - "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/workerpool": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", - "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==" - }, - "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/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.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, "dependencies": { "@sinonjs/commons": { "version": "1.8.1", @@ -3053,16 +581,6 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, - "fill-keys": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/fill-keys/-/fill-keys-1.0.2.tgz", - "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", - "dev": true, - "requires": { - "is-object": "~1.0.1", - "merge-descriptors": "~1.0.0" - } - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3304,12 +822,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, - "is-object": { - "version": "1.0.2", - "resolved": "http://npm.ooapi.com:4873/is-object/-/is-object-1.0.2.tgz", - "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", - "dev": true - }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -3563,12 +1075,6 @@ } } }, - "module-not-found-error": { - "version": "1.0.1", - "resolved": "http://npm.ooapi.com:4873/module-not-found-error/-/module-not-found-error-1.0.1.tgz", - "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", - "dev": true - }, "moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", @@ -3772,17 +1278,6 @@ "ipaddr.js": "1.9.1" } }, - "proxyquire": { - "version": "2.1.3", - "resolved": "http://npm.ooapi.com:4873/proxyquire/-/proxyquire-2.1.3.tgz", - "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", - "dev": true, - "requires": { - "fill-keys": "^1.0.2", - "module-not-found-error": "^1.0.1", - "resolve": "^1.11.1" - } - }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -3958,17 +1453,6 @@ "yargs": "^13.1.0" } }, - "sequelize-mock": { - "version": "0.10.2", - "resolved": "http://npm.ooapi.com:4873/sequelize-mock/-/sequelize-mock-0.10.2.tgz", - "integrity": "sha1-GdOXHM2utbhkFwwkznkqinHxRL0=", - "dev": true, - "requires": { - "bluebird": "^3.4.6", - "inflection": "^1.10.0", - "lodash": "^4.16.4" - } - }, "sequelize-pool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", @@ -4037,6 +1521,16 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "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" + } + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -4052,16 +1546,6 @@ } } }, - "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", @@ -4364,4 +1848,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index c25bd055..5f6f1d0f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { - "name": "forum-express-workspace", - "version": "1.0.0", - "description": "", + "name": "forum-express-grading", + "version": "2.0.0", "main": "_helpers.js", "scripts": { "start": "node app.js", @@ -10,26 +9,21 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/v123582/forum-express-workspace.git" + "url": "git+https://github.com/ALPHACamp/forum-express-grading.git" }, - "author": "", - "license": "ISC", - "bugs": { - "url": "https://github.com/v123582/forum-express-workspace/issues" - }, - "homepage": "https://github.com/v123582/forum-express-workspace#readme", "dependencies": { - "chai": "^4.2.0", "express": "^4.17.1", - "mocha": "^8.2.0", "mysql2": "^2.2.5", + "nodemon": "^2.0.12", "sequelize": "^6.3.5", - "sequelize-cli": "^6.2.0", - "sinon": "^9.2.0", - "supertest": "^5.0.0" + "sequelize-cli": "^6.2.0" }, "devDependencies": { + "chai": "^4.2.0", + "mocha": "^8.2.0", "proxyquire": "^2.1.3", - "sequelize-mock": "^0.10.2" + "sequelize-mock": "^0.10.2", + "sinon": "^9.2.0", + "supertest": "^5.0.0" } -} +} \ No newline at end of file From 7dc7a56d0d7dea94585dd0f47db7143139dce60c Mon Sep 17 00:00:00 2001 From: Serena Tseng <51045074+Carrot7712@users.noreply.github.com> Date: Sat, 6 Nov 2021 00:14:56 +0800 Subject: [PATCH 041/101] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9635c20c..fdf50b79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,9 +11,9 @@ env: # 在 install 前執行的指令 before_install: - - mysql -e 'CREATE DATABASE IF NOT EXISTS forum_test default character set utf8mb4 collate utf8mb4_unicode_ci;' + - mysql -e 'CREATE DATABASE IF NOT EXISTS forum default character set utf8mb4 collate utf8mb4_unicode_ci;' - npm install sequelize-cli -g # 在執行測試之前的指令 before_script: - - sequelize db:migrate \ No newline at end of file + - sequelize db:migrate From 88575dacb96db474e35bd8386b962cc25bed5ca6 Mon Sep 17 00:00:00 2001 From: Serena Tseng <51045074+Carrot7712@users.noreply.github.com> Date: Sat, 6 Nov 2021 00:29:51 +0800 Subject: [PATCH 042/101] Update .travis.yml --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index fdf50b79..f08c1b5e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "10" + - "14" services: - mysql @@ -16,4 +16,5 @@ before_install: # 在執行測試之前的指令 before_script: - - sequelize db:migrate + - sequelize db:migrate + - sequelize db:seed:all From b8259bef909a4e7244ee8ecde30f9dfb07ba21c4 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 18 Nov 2021 13:42:37 +0800 Subject: [PATCH 043/101] Initialize project --- app.js | 4 +++ package-lock.json | 68 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 3 ++- 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index f70e64d6..1eab1f84 100644 --- a/app.js +++ b/app.js @@ -1,7 +1,11 @@ const express = require('express') +const exphbs = require('express-handlebars') const app = express() const port = 3000 +app.engine('handlebars', exphbs({ defaultLayout: 'main' })) +app.set('view engine', 'handlebars') + app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) }) diff --git a/package-lock.json b/package-lock.json index 6cdb461e..96eab130 100644 --- a/package-lock.json +++ b/package-lock.json @@ -561,6 +561,36 @@ "vary": "~1.1.2" } }, + "express-handlebars": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.1.tgz", + "integrity": "sha512-K3Lemki5jkD3sZwDhgBEBk+oAl1xg4nsMJAfpq1AUl5K187/mU1/xKVWt+4RZAHAxlyQFk4YBfX5+00AzLNfWg==", + "requires": { + "glob": "^7.2.0", + "graceful-fs": "^4.2.8", + "handlebars": "^4.7.7" + }, + "dependencies": { + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "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" + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + } + } + }, "ext": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", @@ -716,6 +746,18 @@ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -985,6 +1027,11 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -1152,6 +1199,11 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", @@ -1506,6 +1558,11 @@ "supports-color": "^7.1.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -1672,6 +1729,12 @@ "mime-types": "~2.1.24" } }, + "uglify-js": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", + "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", + "optional": true + }, "umzug": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", @@ -1768,6 +1831,11 @@ "@types/node": "*" } }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, "workerpool": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", diff --git a/package.json b/package.json index dd99a5f1..06c32ce5 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "start": "node app.js", "dev": "nodemon app.js", - "test": "mocha tests --exit --recursive --timeout 5000" + "test": "set \"NODE_ENV=test\" && mocha tests --exit --recursive --timeout 5000" }, "repository": { "type": "git", @@ -21,6 +21,7 @@ "dependencies": { "chai": "^4.2.0", "express": "^4.17.1", + "express-handlebars": "^6.0.1", "mocha": "^8.2.0", "mysql2": "^2.2.5", "sequelize": "^6.3.5", From 52590c922dd4a2474bf6126055476bc6fff70e7c Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 18 Nov 2021 22:41:50 +0800 Subject: [PATCH 044/101] feat:Add restaurant index page --- controller/restController.js | 6 ++++++ package-lock.json | 10 +++++----- package.json | 2 +- routes/index.js | 8 ++++---- views/layouts/main.handlebars | 22 ++++++++++++++++++++++ views/restaurants.handlebars | 3 +++ 6 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 controller/restController.js create mode 100644 views/layouts/main.handlebars create mode 100644 views/restaurants.handlebars diff --git a/controller/restController.js b/controller/restController.js new file mode 100644 index 00000000..d827c187 --- /dev/null +++ b/controller/restController.js @@ -0,0 +1,6 @@ +const restController = { + getRestaurants: (req, res) => { + return res.render('restaurants') + } +} +module.exports = restController \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 96eab130..71ce0eb2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -562,12 +562,12 @@ } }, "express-handlebars": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.1.tgz", - "integrity": "sha512-K3Lemki5jkD3sZwDhgBEBk+oAl1xg4nsMJAfpq1AUl5K187/mU1/xKVWt+4RZAHAxlyQFk4YBfX5+00AzLNfWg==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-5.3.3.tgz", + "integrity": "sha512-/tWy/VmfdaZ5RUZUprgDzcCTj4QEnaXHbtLSXr4ROTpC/3aynrg4nIkn1+eLlcEp4Cs7HkxDlu2jJaz3aBG//w==", "requires": { - "glob": "^7.2.0", - "graceful-fs": "^4.2.8", + "glob": "^7.1.7", + "graceful-fs": "^4.2.7", "handlebars": "^4.7.7" }, "dependencies": { diff --git a/package.json b/package.json index 06c32ce5..31adaa52 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "chai": "^4.2.0", "express": "^4.17.1", - "express-handlebars": "^6.0.1", + "express-handlebars": "^5.3.3", "mocha": "^8.2.0", "mysql2": "^2.2.5", "sequelize": "^6.3.5", diff --git a/routes/index.js b/routes/index.js index fc55e842..779aabeb 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,6 +1,6 @@ -module.exports = (app) => { +const restController = require('../controller/restController') - app.get('/', (req, res) => { - res.send('Hello World!') - }) +module.exports = (app) => { + app.get('/', (req, res) => res.redirect('/restaurants')) + app.get('/restaurants', restController.getRestaurants) } diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars new file mode 100644 index 00000000..298a280e --- /dev/null +++ b/views/layouts/main.handlebars @@ -0,0 +1,22 @@ + + + + + + 餐廳評論網 + + + + +
+
+
+ {{{body}}} +
+
+
+ + + + + \ No newline at end of file diff --git a/views/restaurants.handlebars b/views/restaurants.handlebars new file mode 100644 index 00000000..97b6e76e --- /dev/null +++ b/views/restaurants.handlebars @@ -0,0 +1,3 @@ +
+ restaurants +
\ No newline at end of file From 8ab66e9fe24f2657bdda87884ed4c7743078d920 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 18 Nov 2021 22:45:32 +0800 Subject: [PATCH 045/101] feat:Add admin restaurant index page --- controllers/adminController.js | 7 +++++++ {controller => controllers}/restController.js | 0 routes/index.js | 5 ++++- views/admin/restaurants.handlebars | 3 +++ 4 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 controllers/adminController.js rename {controller => controllers}/restController.js (100%) create mode 100644 views/admin/restaurants.handlebars diff --git a/controllers/adminController.js b/controllers/adminController.js new file mode 100644 index 00000000..717b9027 --- /dev/null +++ b/controllers/adminController.js @@ -0,0 +1,7 @@ +const adminController = { + getRestaurants: (req, res) => { + return res.render('admin/restaurants') + } +} + +module.exports = adminController \ No newline at end of file diff --git a/controller/restController.js b/controllers/restController.js similarity index 100% rename from controller/restController.js rename to controllers/restController.js diff --git a/routes/index.js b/routes/index.js index 779aabeb..85af2bc2 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,6 +1,9 @@ -const restController = require('../controller/restController') +const restController = require('../controllers/restController') +const adminController = require('../controllers/adminController.js') module.exports = (app) => { app.get('/', (req, res) => res.redirect('/restaurants')) app.get('/restaurants', restController.getRestaurants) + app.get('/admin', (req, res) => res.redirect('/admin/restaurants')) + app.get('/admin/restaurants', adminController.getRestaurants) } diff --git a/views/admin/restaurants.handlebars b/views/admin/restaurants.handlebars new file mode 100644 index 00000000..c1e24fc9 --- /dev/null +++ b/views/admin/restaurants.handlebars @@ -0,0 +1,3 @@ +
+ admin restaurants +
\ No newline at end of file From 981adec572423bf5b47912a9e647a0e511c392b9 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 18 Nov 2021 22:58:36 +0800 Subject: [PATCH 046/101] feat:Create user model --- migrations/20211118145538-create-user.js | 36 ++++++++++++++++++++++++ models/user.js | 25 ++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 migrations/20211118145538-create-user.js create mode 100644 models/user.js diff --git a/migrations/20211118145538-create-user.js b/migrations/20211118145538-create-user.js new file mode 100644 index 00000000..0554c75c --- /dev/null +++ b/migrations/20211118145538-create-user.js @@ -0,0 +1,36 @@ +'use strict'; +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Users', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + name: { + type: Sequelize.STRING, + allowNull: false + }, + email: { + type: Sequelize.STRING, + allowNull: false + }, + password: { + type: Sequelize.STRING, + allowNull: false + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Users'); + } +}; \ No newline at end of file diff --git a/models/user.js b/models/user.js new file mode 100644 index 00000000..90c48b43 --- /dev/null +++ b/models/user.js @@ -0,0 +1,25 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class User extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + }; + User.init({ + name: DataTypes.STRING, + email: DataTypes.STRING, + password: DataTypes.STRING + }, { + sequelize, + modelName: 'User', + }); + return User; +}; \ No newline at end of file From d26a398a3a916fd12abe193468c9a1399be4c91c Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 18 Nov 2021 23:12:50 +0800 Subject: [PATCH 047/101] feat:Add userController and signup page --- app.js | 1 + controllers/userController.js | 21 +++++++++++++++++++++ models/index.js | 2 +- package-lock.json | 5 +++++ package.json | 2 ++ routes/index.js | 3 +++ views/signup.handlebars | 27 +++++++++++++++++++++++++++ 7 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 controllers/userController.js create mode 100644 views/signup.handlebars diff --git a/app.js b/app.js index 1eab1f84..b825a8d2 100644 --- a/app.js +++ b/app.js @@ -5,6 +5,7 @@ const port = 3000 app.engine('handlebars', exphbs({ defaultLayout: 'main' })) app.set('view engine', 'handlebars') +app.use(express.urlencoded({extended: true})) app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) diff --git a/controllers/userController.js b/controllers/userController.js new file mode 100644 index 00000000..504a2fe5 --- /dev/null +++ b/controllers/userController.js @@ -0,0 +1,21 @@ +const bcrypt = require('bcryptjs') +const db = require('../models') +const User = db.User + +const userController = { + signUpPage: (req, res) => { + return res.render('signup') + }, + + signUp: (req, res) => { + User.create({ + name: req.body.name, + email: req.body.email, + password: bcrypt.hashSync(req.body.password, bcrypt.genSaltSync(10), null) + }).then(user => { + return res.redirect('/signin') + }) + } +} + +module.exports = userController \ No newline at end of file diff --git a/models/index.js b/models/index.js index 66860356..916d369a 100644 --- a/models/index.js +++ b/models/index.js @@ -23,7 +23,7 @@ fs return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js') }) .forEach(file => { - const model = sequelize['import'](path.join(__dirname, file)) + const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes) db[model.name] = model }) diff --git a/package-lock.json b/package-lock.json index 71ce0eb2..a0109b84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -128,6 +128,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, "binary-extensions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", diff --git a/package.json b/package.json index 31adaa52..6927737a 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ }, "homepage": "https://github.com/v123582/forum-express-workspace#readme", "dependencies": { + "bcryptjs": "^2.4.3", + "body-parser": "^1.19.0", "chai": "^4.2.0", "express": "^4.17.1", "express-handlebars": "^5.3.3", diff --git a/routes/index.js b/routes/index.js index 85af2bc2..6637e25a 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,9 +1,12 @@ const restController = require('../controllers/restController') const adminController = require('../controllers/adminController.js') +const userController = require('../controllers/userController.js') module.exports = (app) => { app.get('/', (req, res) => res.redirect('/restaurants')) app.get('/restaurants', restController.getRestaurants) app.get('/admin', (req, res) => res.redirect('/admin/restaurants')) app.get('/admin/restaurants', adminController.getRestaurants) + app.get('/signup', userController.signUpPage) + app.post('/signup', userController.signUp) } diff --git a/views/signup.handlebars b/views/signup.handlebars new file mode 100644 index 00000000..f6a28e61 --- /dev/null +++ b/views/signup.handlebars @@ -0,0 +1,27 @@ + \ No newline at end of file From 48296fdb608ce233e7b39333782cd831c444feba Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 18 Nov 2021 23:22:15 +0800 Subject: [PATCH 048/101] feat:Confirm user password and unique email --- app.js | 10 +++++++ controllers/userController.js | 31 +++++++++++++++----- package-lock.json | 55 +++++++++++++++++++++++++++++++++++ package.json | 2 ++ views/layouts/main.handlebars | 12 +++++++- 5 files changed, 101 insertions(+), 9 deletions(-) diff --git a/app.js b/app.js index b825a8d2..26570aa6 100644 --- a/app.js +++ b/app.js @@ -1,11 +1,21 @@ const express = require('express') const exphbs = require('express-handlebars') +const flash = require('connect-flash') +const session = require('express-session') const app = express() const port = 3000 app.engine('handlebars', exphbs({ defaultLayout: 'main' })) app.set('view engine', 'handlebars') app.use(express.urlencoded({extended: true})) +app.use(session({ secret: 'secret', resave: false, saveUninitialized: false })) +app.use(flash()) + +app.use((req, res, next) => { + res.locals.success_messages = req.flash('success_messages') + res.locals.error_messages = req.flash('error_messages') + next() +}) app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) diff --git a/controllers/userController.js b/controllers/userController.js index 504a2fe5..9a09ff00 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -8,14 +8,29 @@ const userController = { }, signUp: (req, res) => { - User.create({ - name: req.body.name, - email: req.body.email, - password: bcrypt.hashSync(req.body.password, bcrypt.genSaltSync(10), null) - }).then(user => { - return res.redirect('/signin') - }) - } + // confirm password + if(req.body.passwordCheck !== req.body.password){ + req.flash('error_messages', '兩次密碼輸入不同!') + return res.redirect('/signup') + } else { + // confirm unique user + User.findOne({where: {email: req.body.email}}).then(user => { + if(user){ + req.flash('error_messages', '信箱重複!') + return res.redirect('/signup') + } else { + User.create({ + name: req.body.name, + email: req.body.email, + password: bcrypt.hashSync(req.body.password, bcrypt.genSaltSync(10), null) + }).then(user => { + req.flash('success_messages', '成功註冊帳號!') + return res.redirect('/signin') + }) + } + }) + } + } } module.exports = userController \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a0109b84..d5b88115 100644 --- a/package-lock.json +++ b/package-lock.json @@ -325,6 +325,11 @@ "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.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -596,6 +601,38 @@ } } }, + "express-session": { + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.2.tgz", + "integrity": "sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==", + "requires": { + "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" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "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==" + } + } + }, "ext": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", @@ -1257,6 +1294,11 @@ "ee-first": "1.1.1" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1345,6 +1387,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -1740,6 +1787,14 @@ "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", "optional": true }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, "umzug": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", diff --git a/package.json b/package.json index 6927737a..d107bac7 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,10 @@ "bcryptjs": "^2.4.3", "body-parser": "^1.19.0", "chai": "^4.2.0", + "connect-flash": "^0.1.1", "express": "^4.17.1", "express-handlebars": "^5.3.3", + "express-session": "^1.17.2", "mocha": "^8.2.0", "mysql2": "^2.2.5", "sequelize": "^6.3.5", diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index 298a280e..b0fe6e5e 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -11,7 +11,17 @@
- {{{body}}} + {{#if success_messages}} + + {{/if}} + {{#if error_messages}} + + {{/if}} + {{{body}}}
From 56608af4bd616c01df394d2c61beeb4ad4cdca12 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 18 Nov 2021 23:45:38 +0800 Subject: [PATCH 049/101] feat:Add feature: signInPage, signIn and logout --- app.js | 5 ++++- config/passport.js | 36 +++++++++++++++++++++++++++++++++++ controllers/userController.js | 17 ++++++++++++++++- package-lock.json | 27 ++++++++++++++++++++++++++ package.json | 2 ++ routes/index.js | 5 ++++- views/signin.handlebars | 19 ++++++++++++++++++ 7 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 config/passport.js create mode 100644 views/signin.handlebars diff --git a/app.js b/app.js index 26570aa6..14b7f56c 100644 --- a/app.js +++ b/app.js @@ -2,6 +2,7 @@ const express = require('express') const exphbs = require('express-handlebars') const flash = require('connect-flash') const session = require('express-session') +const passport = require('./config/passport') const app = express() const port = 3000 @@ -9,6 +10,8 @@ app.engine('handlebars', exphbs({ defaultLayout: 'main' })) app.set('view engine', 'handlebars') app.use(express.urlencoded({extended: true})) app.use(session({ secret: 'secret', resave: false, saveUninitialized: false })) +app.use(passport.initialize()) +app.use(passport.session()) app.use(flash()) app.use((req, res, next) => { @@ -21,6 +24,6 @@ app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) }) -require('./routes')(app) +require('./routes')(app, passport) module.exports = app diff --git a/config/passport.js b/config/passport.js new file mode 100644 index 00000000..2ff44c68 --- /dev/null +++ b/config/passport.js @@ -0,0 +1,36 @@ +const passport = require('passport') +const LocalStrategy = require('passport-local') +const bcrypt = require('bcryptjs') +const db = require('../models') +const User = db.User + +// setup passport strategy +passport.use(new LocalStrategy( + // customize user field + { + usernameField: 'email', + passwordField: 'password', + passReqToCallback: true + }, + // authenticate user + (req, username, password, cb) => { + User.findOne({ where: { email: username } }).then(user => { + if (!user) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤')) + if (!bcrypt.compareSync(password, user.password)) return cb(null, false, req.flash('error_messages', '帳號或密碼輸入錯誤!')) + return cb(null, user) + }) + } +)) + +// serialize and deserialize user +passport.serializeUser((user, cb) => { + cb(null, user.id) +}) +passport.deserializeUser((id, cb) => { + User.findByPk(id).then(user => { + user = user.toJSON() // 此處與影片示範不同 + return cb(null, user) + }) +}) + +module.exports = passport \ No newline at end of file diff --git a/controllers/userController.js b/controllers/userController.js index 9a09ff00..b7003660 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -30,7 +30,22 @@ const userController = { } }) } - } + }, + + signInPage: (req, res) => { + return res.render('signin') + }, + + signIn: (req, res) => { + req.flash('success_messages', '成功登入!') + res.redirect('/restaurants') + }, + + logout: (req, res) => { + req.flash('success_messages', '登出成功!') + req.logout() + res.redirect('/signin') + } } module.exports = userController \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d5b88115..c8247c01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1333,6 +1333,28 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "passport": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.0.tgz", + "integrity": "sha512-ln+ue5YaNDS+fes6O5PCzXKSseY5u8MYhX9H5Co4s+HfYI5oqvnHKoOORLYDUPh+8tHvrxugF2GFcUA1Q1Gqfg==", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + } + }, + "passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -1358,6 +1380,11 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", diff --git a/package.json b/package.json index d107bac7..67ba7c98 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,8 @@ "express-session": "^1.17.2", "mocha": "^8.2.0", "mysql2": "^2.2.5", + "passport": "^0.5.0", + "passport-local": "^1.0.0", "sequelize": "^6.3.5", "sequelize-cli": "^6.2.0", "sinon": "^9.2.0", diff --git a/routes/index.js b/routes/index.js index 6637e25a..cac4d4da 100644 --- a/routes/index.js +++ b/routes/index.js @@ -2,11 +2,14 @@ const restController = require('../controllers/restController') const adminController = require('../controllers/adminController.js') const userController = require('../controllers/userController.js') -module.exports = (app) => { +module.exports = (app, passport) => { app.get('/', (req, res) => res.redirect('/restaurants')) app.get('/restaurants', restController.getRestaurants) app.get('/admin', (req, res) => res.redirect('/admin/restaurants')) app.get('/admin/restaurants', adminController.getRestaurants) app.get('/signup', userController.signUpPage) app.post('/signup', userController.signUp) + app.get('/signin', userController.signInPage) + app.post('/signin', passport.authenticate('local', { failureRedirect: '/signin', failureFlash: true }), userController.signIn) + app.get('/logout', userController.logout) } diff --git a/views/signin.handlebars b/views/signin.handlebars new file mode 100644 index 00000000..31f07ff7 --- /dev/null +++ b/views/signin.handlebars @@ -0,0 +1,19 @@ + \ No newline at end of file From 5b288623bd36e0d4c29a71cd98de9e336cf336c6 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 00:03:22 +0800 Subject: [PATCH 050/101] feat:Add navbar to show login status --- app.js | 1 + views/layouts/main.handlebars | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/app.js b/app.js index 14b7f56c..e6ab0e69 100644 --- a/app.js +++ b/app.js @@ -15,6 +15,7 @@ app.use(passport.session()) app.use(flash()) app.use((req, res, next) => { + res.locals.user = req.user res.locals.success_messages = req.flash('success_messages') res.locals.error_messages = req.flash('error_messages') next() diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars index b0fe6e5e..21593b23 100644 --- a/views/layouts/main.handlebars +++ b/views/layouts/main.handlebars @@ -8,6 +8,25 @@ + {{!-- Navbar --}} + +
From 36ddfc61e74821c13fb59b0ee77ed872bd28d036 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 10:05:56 +0800 Subject: [PATCH 051/101] feat:Add isAdmin to users table,and add authentication before rendering pages --- .../20211119014024-add-isAdmin-to-users.js | 14 +++++++++++++ models/user.js | 3 ++- routes/index.js | 21 +++++++++++++++---- 3 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 migrations/20211119014024-add-isAdmin-to-users.js diff --git a/migrations/20211119014024-add-isAdmin-to-users.js b/migrations/20211119014024-add-isAdmin-to-users.js new file mode 100644 index 00000000..60e6fe08 --- /dev/null +++ b/migrations/20211119014024-add-isAdmin-to-users.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.addColumn('Users', 'isAdmin', { + type: Sequelize.BOOLEAN, + defaultValue: false, + }); + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn('Users', 'isAdmin'); + } +}; diff --git a/models/user.js b/models/user.js index 90c48b43..7f949fd6 100644 --- a/models/user.js +++ b/models/user.js @@ -16,7 +16,8 @@ module.exports = (sequelize, DataTypes) => { User.init({ name: DataTypes.STRING, email: DataTypes.STRING, - password: DataTypes.STRING + password: DataTypes.STRING, + isAdmin: DataTypes.BOOLEAN }, { sequelize, modelName: 'User', diff --git a/routes/index.js b/routes/index.js index cac4d4da..2261d648 100644 --- a/routes/index.js +++ b/routes/index.js @@ -3,10 +3,23 @@ const adminController = require('../controllers/adminController.js') const userController = require('../controllers/userController.js') module.exports = (app, passport) => { - app.get('/', (req, res) => res.redirect('/restaurants')) - app.get('/restaurants', restController.getRestaurants) - app.get('/admin', (req, res) => res.redirect('/admin/restaurants')) - app.get('/admin/restaurants', adminController.getRestaurants) + const authenticated = (req, res, next) => { + if (req.isAuthenticated()) { + return next() + } + res.redirect('/signin') + } + const authenticatedAdmin = (req, res, next) => { + if (req.isAuthenticated()) { + if (req.user.isAdmin) { return next() } + return res.redirect('/') + } + res.redirect('/signin') + } + app.get('/', authenticated, (req, res) => res.redirect('/restaurants')) + app.get('/restaurants', authenticated,restController.getRestaurants) + app.get('/admin', authenticatedAdmin,(req, res) => res.redirect('/admin/restaurants')) + app.get('/admin/restaurants', authenticatedAdmin, adminController.getRestaurants) app.get('/signup', userController.signUpPage) app.post('/signup', userController.signUp) app.get('/signin', userController.signInPage) From 73020344ca2cd5038b07bfbe0a2b0ff71bb3fc8c Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 10:14:47 +0800 Subject: [PATCH 052/101] feat:Create restaurant model --- .../20211119021226-create-restaurant.js | 39 +++++++++++++++++++ models/restaurant.js | 27 +++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 migrations/20211119021226-create-restaurant.js create mode 100644 models/restaurant.js diff --git a/migrations/20211119021226-create-restaurant.js b/migrations/20211119021226-create-restaurant.js new file mode 100644 index 00000000..9ae279d5 --- /dev/null +++ b/migrations/20211119021226-create-restaurant.js @@ -0,0 +1,39 @@ +'use strict'; +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Restaurants', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + name: { + type: Sequelize.STRING + }, + tel: { + type: Sequelize.STRING + }, + address: { + type: Sequelize.STRING + }, + opening_hours: { + type: Sequelize.STRING + }, + description: { + type: Sequelize.TEXT + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Restaurants'); + } +}; \ No newline at end of file diff --git a/models/restaurant.js b/models/restaurant.js new file mode 100644 index 00000000..b9db8597 --- /dev/null +++ b/models/restaurant.js @@ -0,0 +1,27 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Restaurant extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + }; + Restaurant.init({ + name: DataTypes.STRING, + tel: DataTypes.STRING, + address: DataTypes.STRING, + opening_hours: DataTypes.STRING, + description: DataTypes.TEXT + }, { + sequelize, + modelName: 'Restaurant', + }); + return Restaurant; +}; \ No newline at end of file From 1dde1f0c7cdb91b4b6f393ae69c7db84e821e2da Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 10:21:35 +0800 Subject: [PATCH 053/101] feat:Add admin restaurant index page --- controllers/adminController.js | 13 +++++++-- views/admin/restaurants.handlebars | 44 ++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/controllers/adminController.js b/controllers/adminController.js index 717b9027..9ed5de0d 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -1,7 +1,14 @@ +const db = require('../models') +const Restaurant = db.Restaurant + const adminController = { - getRestaurants: (req, res) => { - return res.render('admin/restaurants') - } + getRestaurants: (req, res) => { + return Restaurant.findAll({raw: true, nest: true}) + .then(restaurants => { + return res.render('admin/restaurants', { restaurants }) + }) + } } + module.exports = adminController \ No newline at end of file diff --git a/views/admin/restaurants.handlebars b/views/admin/restaurants.handlebars index c1e24fc9..351678bd 100644 --- a/views/admin/restaurants.handlebars +++ b/views/admin/restaurants.handlebars @@ -1,3 +1,41 @@ -
- admin restaurants -
\ No newline at end of file +

餐廳後台

+ + + + + +
+
+ + + + + + + + + + + {{#each restaurants}} + + + + + + {{/each}} + +
#Name#
{{this.id}}{{this.name}} + + +
+ +
+
\ No newline at end of file From 2ec789f94775f46e9ade2067ec4cd61eeeae2f96 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 13:03:53 +0800 Subject: [PATCH 054/101] feat:Add admin restaurant create form and admin restaurant post feature --- controllers/adminController.js | 22 ++++++++++++++++++++++ routes/index.js | 2 ++ views/admin/create.handlebars | 28 ++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 views/admin/create.handlebars diff --git a/controllers/adminController.js b/controllers/adminController.js index 9ed5de0d..4e700ecd 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -7,6 +7,28 @@ const adminController = { .then(restaurants => { return res.render('admin/restaurants', { restaurants }) }) + }, + + createRestaurant: (req, res) => { + return res.render('admin/create') + }, + + postRestaurant: (req, res) => { + if (!req.body.name) { + req.flash('error_messages', "name didn't exist") + return res.redirect('back') + } + return Restaurant.create({ + name: req.body.name, + tel: req.body.tel, + address: req.body.address, + opening_hours: req.body.opening_hours, + description: req.body.description + }) + .then((restaurant) => { + req.flash('success_messages', 'restaurant was successfully created') + res.redirect('/admin/restaurants') + }) } } diff --git a/routes/index.js b/routes/index.js index 2261d648..dd2870c9 100644 --- a/routes/index.js +++ b/routes/index.js @@ -20,6 +20,8 @@ module.exports = (app, passport) => { app.get('/restaurants', authenticated,restController.getRestaurants) app.get('/admin', authenticatedAdmin,(req, res) => res.redirect('/admin/restaurants')) app.get('/admin/restaurants', authenticatedAdmin, adminController.getRestaurants) + app.get('/admin/restaurants/create', authenticatedAdmin, adminController.createRestaurant) + app.post('/admin/restaurants', authenticatedAdmin, adminController.postRestaurant) app.get('/signup', userController.signUpPage) app.post('/signup', userController.signUp) app.get('/signin', userController.signInPage) diff --git a/views/admin/create.handlebars b/views/admin/create.handlebars new file mode 100644 index 00000000..83881311 --- /dev/null +++ b/views/admin/create.handlebars @@ -0,0 +1,28 @@ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
\ No newline at end of file From 5394221358f72e68ec58548429e9f7b509a94703 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 13:10:02 +0800 Subject: [PATCH 055/101] feat:Add admin restaurant page --- controllers/adminController.js | 7 +++++++ routes/index.js | 1 + views/admin/restaurant.handlebars | 26 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 views/admin/restaurant.handlebars diff --git a/controllers/adminController.js b/controllers/adminController.js index 4e700ecd..cf48093a 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -29,6 +29,13 @@ const adminController = { req.flash('success_messages', 'restaurant was successfully created') res.redirect('/admin/restaurants') }) + }, + + getRestaurant: (req, res) => { + return Restaurant.findByPk(req.params.id, {raw:true}) + .then(restaurant => { + return res.render('admin/restaurant', { restaurant }) + }) } } diff --git a/routes/index.js b/routes/index.js index dd2870c9..9ba11745 100644 --- a/routes/index.js +++ b/routes/index.js @@ -22,6 +22,7 @@ module.exports = (app, passport) => { app.get('/admin/restaurants', authenticatedAdmin, adminController.getRestaurants) app.get('/admin/restaurants/create', authenticatedAdmin, adminController.createRestaurant) app.post('/admin/restaurants', authenticatedAdmin, adminController.postRestaurant) + app.get('/admin/restaurants/:id', authenticatedAdmin, adminController.getRestaurant) app.get('/signup', userController.signUpPage) app.post('/signup', userController.signUp) app.get('/signin', userController.signInPage) diff --git a/views/admin/restaurant.handlebars b/views/admin/restaurant.handlebars new file mode 100644 index 00000000..deb5eb99 --- /dev/null +++ b/views/admin/restaurant.handlebars @@ -0,0 +1,26 @@ +
+
+

{{restaurant.name}}

+
+ +
+
+
+
    +
  • Opening Hour: {{restaurant.opening_hours}}
  • +
  • Tel: {{restaurant.tel}}
  • +
  • Address: {{restaurant.address}}
  • +
+
+
+
+

{{restaurant.description}}

+
+
+
+ +
+ +
+
+回上一頁 \ No newline at end of file From 955c9a219f8e8e91e8a29af9ff0a600c1af20e4d Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 13:17:54 +0800 Subject: [PATCH 056/101] feat:Update admin create page for editing usage,and add admin restaurant put feature --- app.js | 2 ++ controllers/adminController.js | 29 +++++++++++++++++++++++++++++ package-lock.json | 21 +++++++++++++++++++++ package.json | 1 + routes/index.js | 2 ++ views/admin/create.handlebars | 16 ++++++++++------ 6 files changed, 65 insertions(+), 6 deletions(-) diff --git a/app.js b/app.js index e6ab0e69..968c89d6 100644 --- a/app.js +++ b/app.js @@ -3,11 +3,13 @@ const exphbs = require('express-handlebars') const flash = require('connect-flash') const session = require('express-session') const passport = require('./config/passport') +const methodOverride = require('method-override') const app = express() const port = 3000 app.engine('handlebars', exphbs({ defaultLayout: 'main' })) app.set('view engine', 'handlebars') +app.use(methodOverride('_method')) app.use(express.urlencoded({extended: true})) app.use(session({ secret: 'secret', resave: false, saveUninitialized: false })) app.use(passport.initialize()) diff --git a/controllers/adminController.js b/controllers/adminController.js index cf48093a..7d4623e2 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -36,6 +36,35 @@ const adminController = { .then(restaurant => { return res.render('admin/restaurant', { restaurant }) }) + }, + + editRestaurant: (req, res) => { + return Restaurant.findByPk(req.params.id, {raw:true}) + .then(restaurant => { + return res.render('admin/create', { restaurant } ) + }) + }, + + putRestaurant: (req, res) => { + if(!req.body.name){ + req.flash('error_messages', "name didn't exist") + return res.redirect('back') + } + + return Restaurant.findByPk(req.params.id) + .then((restaurant) => { + restaurant.update({ + name: req.body.name, + tel: req.body.tel, + address: req.body.address, + opening_hours: req.body.opening_hours, + description: req.body.description + }) + .then((restaurant) => { + req.flash('success_messages', 'restaurant was successfully to update') + res.redirect('/admin/restaurants') + }) + }) } } diff --git a/package-lock.json b/package-lock.json index c8247c01..5960471c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1038,6 +1038,27 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, + "method-override": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-3.0.0.tgz", + "integrity": "sha512-IJ2NNN/mSl9w3kzWB92rcdHpz+HjkxhDJWNDBqSlas+zQdP8wBiJzITPg08M/k2uVvMow7Sk41atndNtt/PHSA==", + "requires": { + "debug": "3.1.0", + "methods": "~1.1.2", + "parseurl": "~1.3.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", diff --git a/package.json b/package.json index 67ba7c98..c450d248 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "express": "^4.17.1", "express-handlebars": "^5.3.3", "express-session": "^1.17.2", + "method-override": "^3.0.0", "mocha": "^8.2.0", "mysql2": "^2.2.5", "passport": "^0.5.0", diff --git a/routes/index.js b/routes/index.js index 9ba11745..ea9fa444 100644 --- a/routes/index.js +++ b/routes/index.js @@ -23,6 +23,8 @@ module.exports = (app, passport) => { app.get('/admin/restaurants/create', authenticatedAdmin, adminController.createRestaurant) app.post('/admin/restaurants', authenticatedAdmin, adminController.postRestaurant) app.get('/admin/restaurants/:id', authenticatedAdmin, adminController.getRestaurant) + app.get('/admin/restaurants/:id/edit', authenticatedAdmin, adminController.editRestaurant) + app.put('/admin/restaurants/:id', authenticatedAdmin, adminController.putRestaurant) app.get('/signup', userController.signUpPage) app.post('/signup', userController.signUp) app.get('/signin', userController.signInPage) diff --git a/views/admin/create.handlebars b/views/admin/create.handlebars index 83881311..c2b30f43 100644 --- a/views/admin/create.handlebars +++ b/views/admin/create.handlebars @@ -1,27 +1,31 @@ -
+{{#if restaurant}} + +{{else}} + +{{/if}}
- +
- +
- +
- +
- +
From 1723190c9067098361940b28428691c8b108f8c3 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 13:21:24 +0800 Subject: [PATCH 057/101] feat:Add admin restaurant delete feature --- controllers/adminController.js | 10 ++++++++++ routes/index.js | 1 + 2 files changed, 11 insertions(+) diff --git a/controllers/adminController.js b/controllers/adminController.js index 7d4623e2..941a18da 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -65,6 +65,16 @@ const adminController = { res.redirect('/admin/restaurants') }) }) + }, + + deleteRestaurant: (req, res) => { + return Restaurant.findByPk(req.params.id) + .then((restaurant) => { + restaurant.destroy() + .then((restaurant) => { + res.redirect('/admin/restaurants') + }) + }) } } diff --git a/routes/index.js b/routes/index.js index ea9fa444..9b66ebe2 100644 --- a/routes/index.js +++ b/routes/index.js @@ -25,6 +25,7 @@ module.exports = (app, passport) => { app.get('/admin/restaurants/:id', authenticatedAdmin, adminController.getRestaurant) app.get('/admin/restaurants/:id/edit', authenticatedAdmin, adminController.editRestaurant) app.put('/admin/restaurants/:id', authenticatedAdmin, adminController.putRestaurant) + app.delete('/admin/restaurants/:id', authenticatedAdmin, adminController.deleteRestaurant) app.get('/signup', userController.signUpPage) app.post('/signup', userController.signUp) app.get('/signin', userController.signInPage) From c32572d6f18469277ab8d18b6fb3beea9e640711 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 23:12:19 +0800 Subject: [PATCH 058/101] feat:Add image to restaurants and add image upload feature --- app.js | 1 + controllers/adminController.js | 89 +++++++--- ...20211119052746-add-image-to-restaurants.js | 13 ++ models/restaurant.js | 3 +- package-lock.json | 159 ++++++++++++++++++ package.json | 1 + routes/index.js | 13 +- views/admin/create.handlebars | 9 +- views/admin/restaurant.handlebars | 5 +- 9 files changed, 264 insertions(+), 29 deletions(-) create mode 100644 migrations/20211119052746-add-image-to-restaurants.js diff --git a/app.js b/app.js index 968c89d6..a662253f 100644 --- a/app.js +++ b/app.js @@ -23,6 +23,7 @@ app.use((req, res, next) => { next() }) +app.use('/upload', express.static(__dirname + '/upload')) app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) }) diff --git a/controllers/adminController.js b/controllers/adminController.js index 941a18da..6aaddb1f 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -1,3 +1,4 @@ +const fs = require('fs') const db = require('../models') const Restaurant = db.Restaurant @@ -18,17 +19,38 @@ const adminController = { req.flash('error_messages', "name didn't exist") return res.redirect('back') } - return Restaurant.create({ - name: req.body.name, - tel: req.body.tel, - address: req.body.address, - opening_hours: req.body.opening_hours, - description: req.body.description - }) - .then((restaurant) => { + + const { file } = req // equal to const file = req.file + if (file) { + fs.readFile(file.path, (err, data) => { + if (err) console.log('Error: ', err) + fs.writeFile(`upload/${file.originalname}`, data, () => { + return Restaurant.create({ + name: req.body.name, + tel: req.body.tel, + address: req.body.address, + opening_hours: req.body.opening_hours, + description: req.body.description, + image: file ? `/upload/${file.originalname}` : null + }).then((restaurant) => { + req.flash('success_messages', 'restaurant was successfully created') + return res.redirect('/admin/restaurants') + }) + }) + }) + } else { + return Restaurant.create({ + name: req.body.name, + tel: req.body.tel, + address: req.body.address, + opening_hours: req.body.opening_hours, + description: req.body.description, + image: null + }).then((restaurant) => { req.flash('success_messages', 'restaurant was successfully created') - res.redirect('/admin/restaurants') + return res.redirect('/admin/restaurants') }) + } }, getRestaurant: (req, res) => { @@ -46,25 +68,48 @@ const adminController = { }, putRestaurant: (req, res) => { - if(!req.body.name){ + if (!req.body.name) { req.flash('error_messages', "name didn't exist") return res.redirect('back') } - - return Restaurant.findByPk(req.params.id) - .then((restaurant) => { - restaurant.update({ - name: req.body.name, - tel: req.body.tel, - address: req.body.address, - opening_hours: req.body.opening_hours, - description: req.body.description + + const { file } = req + if (file) { + fs.readFile(file.path, (err, data) => { + if (err) console.log('Error: ', err) + fs.writeFile(`upload/${file.originalname}`, data, () => { + return Restaurant.findByPk(req.params.id) + .then((restaurant) => { + restaurant.update({ + name: req.body.name, + tel: req.body.tel, + address: req.body.address, + opening_hours: req.body.opening_hours, + description: req.body.description, + image: file ? `/upload/${file.originalname}` : restaurant.image + }).then((restaurant) => { + req.flash('success_messages', 'restaurant was successfully to update') + res.redirect('/admin/restaurants') + }) + }) }) + }) + } else { + return Restaurant.findByPk(req.params.id) .then((restaurant) => { - req.flash('success_messages', 'restaurant was successfully to update') - res.redirect('/admin/restaurants') + restaurant.update({ + name: req.body.name, + tel: req.body.tel, + address: req.body.address, + opening_hours: req.body.opening_hours, + description: req.body.description, + image: restaurant.image + }).then((restaurant) => { + req.flash('success_messages', 'restaurant was successfully to update') + res.redirect('/admin/restaurants') + }) }) - }) + } }, deleteRestaurant: (req, res) => { diff --git a/migrations/20211119052746-add-image-to-restaurants.js b/migrations/20211119052746-add-image-to-restaurants.js new file mode 100644 index 00000000..d6c12e1d --- /dev/null +++ b/migrations/20211119052746-add-image-to-restaurants.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.addColumn( 'Restaurants', 'image', { + type: Sequelize.STRING + }); + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn( 'Restaurants', 'image' ); + } +}; diff --git a/models/restaurant.js b/models/restaurant.js index b9db8597..7ad9a01a 100644 --- a/models/restaurant.js +++ b/models/restaurant.js @@ -18,7 +18,8 @@ module.exports = (sequelize, DataTypes) => { tel: DataTypes.STRING, address: DataTypes.STRING, opening_hours: DataTypes.STRING, - description: DataTypes.TEXT + description: DataTypes.TEXT, + image: DataTypes.STRING }, { sequelize, modelName: 'Restaurant', diff --git a/package-lock.json b/package-lock.json index 5960471c..c80a3d76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,6 +100,11 @@ "picomatch": "^2.0.4" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -182,6 +187,38 @@ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, + "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": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "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": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -316,6 +353,46 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "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" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "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==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "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" + } + } + } + }, "config-chain": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", @@ -358,6 +435,11 @@ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" }, + "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==" + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -408,6 +490,33 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "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": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -1203,6 +1312,31 @@ "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" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } + } + }, "mysql2": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.2.5.tgz", @@ -1307,6 +1441,11 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -1411,6 +1550,11 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, + "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==" + }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -1678,6 +1822,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -1829,6 +1978,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "uglify-js": { "version": "3.14.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", @@ -1964,6 +2118,11 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "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.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/package.json b/package.json index c450d248..fc06d59b 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "express-session": "^1.17.2", "method-override": "^3.0.0", "mocha": "^8.2.0", + "multer": "^1.4.3", "mysql2": "^2.2.5", "passport": "^0.5.0", "passport-local": "^1.0.0", diff --git a/routes/index.js b/routes/index.js index 9b66ebe2..e09002cc 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,6 +1,8 @@ const restController = require('../controllers/restController') const adminController = require('../controllers/adminController.js') const userController = require('../controllers/userController.js') +const multer = require('multer') +const upload = multer({ dest: 'temp/' }) module.exports = (app, passport) => { const authenticated = (req, res, next) => { @@ -16,16 +18,23 @@ module.exports = (app, passport) => { } res.redirect('/signin') } + //瀏覽首頁 app.get('/', authenticated, (req, res) => res.redirect('/restaurants')) app.get('/restaurants', authenticated,restController.getRestaurants) + //瀏覽後台 app.get('/admin', authenticatedAdmin,(req, res) => res.redirect('/admin/restaurants')) app.get('/admin/restaurants', authenticatedAdmin, adminController.getRestaurants) + //新增餐廳資料 app.get('/admin/restaurants/create', authenticatedAdmin, adminController.createRestaurant) - app.post('/admin/restaurants', authenticatedAdmin, adminController.postRestaurant) + app.post('/admin/restaurants', authenticatedAdmin, upload.single('image'), adminController.postRestaurant) + //瀏覽單一餐廳 app.get('/admin/restaurants/:id', authenticatedAdmin, adminController.getRestaurant) + //編輯餐廳資料 app.get('/admin/restaurants/:id/edit', authenticatedAdmin, adminController.editRestaurant) - app.put('/admin/restaurants/:id', authenticatedAdmin, adminController.putRestaurant) + app.put('/admin/restaurants/:id', authenticatedAdmin, upload.single('image'), adminController.putRestaurant) + //刪除餐廳資料 app.delete('/admin/restaurants/:id', authenticatedAdmin, adminController.deleteRestaurant) + //註冊、登入、登出 app.get('/signup', userController.signUpPage) app.post('/signup', userController.signUp) app.get('/signin', userController.signInPage) diff --git a/views/admin/create.handlebars b/views/admin/create.handlebars index c2b30f43..632028fc 100644 --- a/views/admin/create.handlebars +++ b/views/admin/create.handlebars @@ -1,7 +1,7 @@ {{#if restaurant}} - + {{else}} - + {{/if}}
@@ -28,5 +28,10 @@
+
+ + +
+ \ No newline at end of file diff --git a/views/admin/restaurant.handlebars b/views/admin/restaurant.handlebars index deb5eb99..e6b1fa59 100644 --- a/views/admin/restaurant.handlebars +++ b/views/admin/restaurant.handlebars @@ -4,6 +4,7 @@
+
    @@ -21,6 +22,6 @@
    -
    -
    +
    +
    回上一頁 \ No newline at end of file From b92d2bbdcc964ee6e276d4a5168a439bd60599ad Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 23:29:31 +0800 Subject: [PATCH 059/101] feat:Add user seed data and restaurant seed data --- package-lock.json | 5 +++ package.json | 1 + seeders/20211119151608-users-seed-file.js | 33 +++++++++++++++++++ .../20211119152133-restaurants-seed-file.js | 24 ++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 seeders/20211119151608-users-seed-file.js create mode 100644 seeders/20211119152133-restaurants-seed-file.js diff --git a/package-lock.json b/package-lock.json index c80a3d76..a60b7a11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -757,6 +757,11 @@ } } }, + "faker": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", + "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==" + }, "fast-safe-stringify": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", diff --git a/package.json b/package.json index fc06d59b..7d108812 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "express": "^4.17.1", "express-handlebars": "^5.3.3", "express-session": "^1.17.2", + "faker": "^5.5.3", "method-override": "^3.0.0", "mocha": "^8.2.0", "multer": "^1.4.3", diff --git a/seeders/20211119151608-users-seed-file.js b/seeders/20211119151608-users-seed-file.js new file mode 100644 index 00000000..41bdde72 --- /dev/null +++ b/seeders/20211119151608-users-seed-file.js @@ -0,0 +1,33 @@ +'use strict'; +const bcrypt = require('bcryptjs') + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.bulkInsert('Users', [{ + email: 'root@example.com', + password: bcrypt.hashSync('12345678', bcrypt.genSaltSync(10), null), + isAdmin: true, + name: 'root', + createdAt: new Date(), + updatedAt: new Date() + }, { + email: 'user1@example.com', + password: bcrypt.hashSync('12345678', bcrypt.genSaltSync(10), null), + isAdmin: false, + name: 'user1', + createdAt: new Date(), + updatedAt: new Date() + }, { + email: 'user2@example.com', + password: bcrypt.hashSync('12345678', bcrypt.genSaltSync(10), null), + isAdmin: false, + name: 'user2', + createdAt: new Date(), + updatedAt: new Date() + }], {}) + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Users', null, {}) + } +}; diff --git a/seeders/20211119152133-restaurants-seed-file.js b/seeders/20211119152133-restaurants-seed-file.js new file mode 100644 index 00000000..fccf46e2 --- /dev/null +++ b/seeders/20211119152133-restaurants-seed-file.js @@ -0,0 +1,24 @@ +'use strict'; +const faker = require('faker') + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.bulkInsert('Restaurants', + Array.from({ length: 50 }).map((d, i) => + ({ + name: faker.name.findName(), + tel: faker.phone.phoneNumber(), + address: faker.address.streetAddress(), + opening_hours: '08:00', + image: `https://loremflickr.com/320/240/restaurant,food/?random=${Math.random() * 100}`, + description: faker.lorem.text(), + createdAt: new Date(), + updatedAt: new Date() + }) + ), {}) + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.bulkDelete('Restaurants', null, {}) + } +}; From b47df7d460670a344bfdf4e5039e1bc16605f668 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 23:39:03 +0800 Subject: [PATCH 060/101] Install pg and update production config --- config/config.json | 13 ++++--- package-lock.json | 95 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/config/config.json b/config/config.json index 987b7880..e65fd92f 100644 --- a/config/config.json +++ b/config/config.json @@ -7,11 +7,14 @@ "dialect": "mysql" }, "production": { - "username": "root", - "password": null, - "database": "database_production", - "host": "127.0.0.1", - "dialect": "mysql" + "use_env_variable": "DATABASE_URL", + "dialect": "postgres", + "protocol": "postgres", + "dialectOptions": { + "ssl": { + "rejectUnauthorized": false + } + } }, "travis": { "username": "travis", diff --git a/package-lock.json b/package-lock.json index a60b7a11..a708ac42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -192,6 +192,11 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, "busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", @@ -1493,6 +1498,11 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1550,11 +1560,88 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" }, + "pg": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz", + "integrity": "sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.4.1", + "pg-protocol": "^1.5.0", + "pg-types": "^2.1.0", + "pgpass": "1.x" + } + }, + "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==" + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz", + "integrity": "sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ==" + }, + "pg-protocol": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz", + "integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", + "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", + "requires": { + "split2": "^3.1.1" + } + }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -1812,6 +1899,14 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", diff --git a/package.json b/package.json index 7d108812..dba95f56 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "mysql2": "^2.2.5", "passport": "^0.5.0", "passport-local": "^1.0.0", + "pg": "^8.7.1", "sequelize": "^6.3.5", "sequelize-cli": "^6.2.0", "sinon": "^9.2.0", From b4fb009003c74d218fc5029b26ff224a4d4523aa Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 19 Nov 2021 23:54:39 +0800 Subject: [PATCH 061/101] Listen to process.env.PORT & define Procfile --- Procfile | 1 + app.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 Procfile diff --git a/Procfile b/Procfile new file mode 100644 index 00000000..6feca7ec --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: NODE_ENV=production node app.js \ No newline at end of file diff --git a/app.js b/app.js index a662253f..7c08c0b6 100644 --- a/app.js +++ b/app.js @@ -5,7 +5,7 @@ const session = require('express-session') const passport = require('./config/passport') const methodOverride = require('method-override') const app = express() -const port = 3000 +const port = process.env.PORT || 3000 app.engine('handlebars', exphbs({ defaultLayout: 'main' })) app.set('view engine', 'handlebars') From da51bf4427fd700e08a71ce0d68f728f810e9fb9 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Sat, 20 Nov 2021 00:18:01 +0800 Subject: [PATCH 062/101] feat:Install Imgur api and update admin POST and PUT --- .env.example | 1 + app.js | 3 + controllers/adminController.js | 80 +++++++++--------- package-lock.json | 146 +++++++++++++++++++++++++++++++++ package.json | 2 + 5 files changed, 193 insertions(+), 39 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..a4ff3c30 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +IMGUR_CLIENT_ID = \ No newline at end of file diff --git a/app.js b/app.js index 7c08c0b6..0a19e64f 100644 --- a/app.js +++ b/app.js @@ -4,6 +4,9 @@ const flash = require('connect-flash') const session = require('express-session') const passport = require('./config/passport') const methodOverride = require('method-override') +if (process.env.NODE_ENV !== 'production') { + require('dotenv').config() +} const app = express() const port = process.env.PORT || 3000 diff --git a/controllers/adminController.js b/controllers/adminController.js index 6aaddb1f..a22effc3 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -1,4 +1,6 @@ const fs = require('fs') +const imgur = require('imgur-node-api') +const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID const db = require('../models') const Restaurant = db.Restaurant @@ -15,30 +17,29 @@ const adminController = { }, postRestaurant: (req, res) => { - if (!req.body.name) { + if(!req.body.name){ req.flash('error_messages', "name didn't exist") return res.redirect('back') } - - const { file } = req // equal to const file = req.file + + const { file } = req if (file) { - fs.readFile(file.path, (err, data) => { - if (err) console.log('Error: ', err) - fs.writeFile(`upload/${file.originalname}`, data, () => { - return Restaurant.create({ - name: req.body.name, - tel: req.body.tel, - address: req.body.address, - opening_hours: req.body.opening_hours, - description: req.body.description, - image: file ? `/upload/${file.originalname}` : null - }).then((restaurant) => { - req.flash('success_messages', 'restaurant was successfully created') - return res.redirect('/admin/restaurants') - }) + imgur.setClientID(IMGUR_CLIENT_ID); + imgur.upload(file.path, (err, img) => { + return Restaurant.create({ + name: req.body.name, + tel: req.body.tel, + address: req.body.address, + opening_hours: req.body.opening_hours, + description: req.body.description, + image: file ? img.data.link : null, + }).then((restaurant) => { + req.flash('success_messages', 'restaurant was successfully created') + return res.redirect('/admin/restaurants') }) }) - } else { + } + else { return Restaurant.create({ name: req.body.name, tel: req.body.tel, @@ -50,7 +51,7 @@ const adminController = { req.flash('success_messages', 'restaurant was successfully created') return res.redirect('/admin/restaurants') }) - } + } }, getRestaurant: (req, res) => { @@ -68,33 +69,33 @@ const adminController = { }, putRestaurant: (req, res) => { - if (!req.body.name) { + if(!req.body.name){ req.flash('error_messages', "name didn't exist") return res.redirect('back') } - + const { file } = req if (file) { - fs.readFile(file.path, (err, data) => { - if (err) console.log('Error: ', err) - fs.writeFile(`upload/${file.originalname}`, data, () => { - return Restaurant.findByPk(req.params.id) + imgur.setClientID(IMGUR_CLIENT_ID); + imgur.upload(file.path, (err, img) => { + return Restaurant.findByPk(req.params.id) + .then((restaurant) => { + restaurant.update({ + name: req.body.name, + tel: req.body.tel, + address: req.body.address, + opening_hours: req.body.opening_hours, + description: req.body.description, + image: file ? img.data.link : restaurant.image, + }) .then((restaurant) => { - restaurant.update({ - name: req.body.name, - tel: req.body.tel, - address: req.body.address, - opening_hours: req.body.opening_hours, - description: req.body.description, - image: file ? `/upload/${file.originalname}` : restaurant.image - }).then((restaurant) => { - req.flash('success_messages', 'restaurant was successfully to update') - res.redirect('/admin/restaurants') - }) + req.flash('success_messages', 'restaurant was successfully to update') + res.redirect('/admin/restaurants') }) - }) + }) }) - } else { + } + else { return Restaurant.findByPk(req.params.id) .then((restaurant) => { restaurant.update({ @@ -104,7 +105,8 @@ const adminController = { opening_hours: req.body.opening_hours, description: req.body.description, image: restaurant.image - }).then((restaurant) => { + }) + .then((restaurant) => { req.flash('success_messages', 'restaurant was successfully to update') res.redirect('/admin/restaurants') }) diff --git a/package-lock.json b/package-lock.json index a708ac42..682fe855 100644 --- a/package-lock.json +++ b/package-lock.json @@ -123,11 +123,21 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "aws-sign": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.2.0.tgz", + "integrity": "sha1-xVAThWyBlOyFSgy+yQqrWgTOOsU=" + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -165,6 +175,14 @@ "type-is": "~1.6.17" } }, + "boom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.3.8.tgz", + "integrity": "sha1-yM2wQUNZEnQWKMBE7Mcy0dF8Ceo=", + "requires": { + "hoek": "0.7.x" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -430,6 +448,11 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" }, + "cookie-jar": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.2.0.tgz", + "integrity": "sha1-ZOzAasl423leS1KQy+SLo3gUAPo=" + }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -445,6 +468,14 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "cryptiles": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.1.3.tgz", + "integrity": "sha1-GlVnNPBtJLo0hirpy55wmjr7/xw=", + "requires": { + "boom": "0.3.x" + } + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -527,6 +558,11 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" }, + "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", @@ -807,6 +843,11 @@ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==" }, + "forever-agent": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.2.0.tgz", + "integrity": "sha1-4cJcetROCcOPIzh2x2/MJP+EOx8=" + }, "form-data": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", @@ -932,11 +973,27 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "hawk": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-0.10.2.tgz", + "integrity": "sha1-mzYd7pWpMWQObVBOBWCaj8OsRdI=", + "requires": { + "boom": "0.3.x", + "cryptiles": "0.1.x", + "hoek": "0.7.x", + "sntp": "0.1.x" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, + "hoek": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.7.6.tgz", + "integrity": "sha1-YPvZBFV1Qc0rh5Wr8wihs3cOFVo=" + }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -957,6 +1014,14 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "imgur-node-api": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/imgur-node-api/-/imgur-node-api-0.1.0.tgz", + "integrity": "sha1-iJU25/x9/FyYXHtVeMGuwxyzwYY=", + "requires": { + "request": "~2.16.6" + } + }, "inflection": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", @@ -1071,6 +1136,11 @@ "esprima": "^4.0.0" } }, + "json-stringify-safe": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-3.0.0.tgz", + "integrity": "sha1-nbew5TDH8onF6MhDKvGRwv91pbM=" + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -1451,6 +1521,11 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "oauth-sign": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.2.0.tgz", + "integrity": "sha1-oOahcV2u0GLzIrYit/5a/RA1tuI=" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1718,6 +1793,64 @@ "picomatch": "^2.2.1" } }, + "request": { + "version": "2.16.6", + "resolved": "https://registry.npmjs.org/request/-/request-2.16.6.tgz", + "integrity": "sha1-hy/kRa5y3iZrN4edatfclI+gHK0=", + "requires": { + "aws-sign": "~0.2.0", + "cookie-jar": "~0.2.0", + "forever-agent": "~0.2.0", + "form-data": "~0.0.3", + "hawk": "~0.10.2", + "json-stringify-safe": "~3.0.0", + "mime": "~1.2.7", + "node-uuid": "~1.4.0", + "oauth-sign": "~0.2.0", + "qs": "~0.5.4", + "tunnel-agent": "~0.2.0" + }, + "dependencies": { + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "requires": { + "delayed-stream": "0.0.5" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=" + }, + "form-data": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.0.10.tgz", + "integrity": "sha1-2zRaU3jYau6x7V1VO4aawZLS9e0=", + "requires": { + "async": "~0.2.7", + "combined-stream": "~0.0.4", + "mime": "~1.2.2" + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=" + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "qs": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz", + "integrity": "sha1-MbGtBYVnZRxSaSFQa5qHk5EaA4Q=" + } + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -1894,6 +2027,14 @@ "supports-color": "^7.1.0" } }, + "sntp": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.1.4.tgz", + "integrity": "sha1-XvSBuVGnspr/30r9fyaDj8ESD4Q=", + "requires": { + "hoek": "0.7.x" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -2059,6 +2200,11 @@ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, + "tunnel-agent": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.2.0.tgz", + "integrity": "sha1-aFPCr7GyEJ5FYp5JK9419Fnqaeg=" + }, "type": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", diff --git a/package.json b/package.json index dba95f56..7d90b087 100644 --- a/package.json +++ b/package.json @@ -23,10 +23,12 @@ "body-parser": "^1.19.0", "chai": "^4.2.0", "connect-flash": "^0.1.1", + "dotenv": "^10.0.0", "express": "^4.17.1", "express-handlebars": "^5.3.3", "express-session": "^1.17.2", "faker": "^5.5.3", + "imgur-node-api": "^0.1.0", "method-override": "^3.0.0", "mocha": "^8.2.0", "multer": "^1.4.3", From da2fa70e62d5482c8f05ae7a8a5f40ed9bab026f Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Sat, 20 Nov 2021 08:59:28 +0800 Subject: [PATCH 063/101] [Assignment Preparation] ensureAuthenticated & getUser --- app.js | 3 ++- routes/index.js | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index 0a19e64f..79c8245a 100644 --- a/app.js +++ b/app.js @@ -4,6 +4,7 @@ const flash = require('connect-flash') const session = require('express-session') const passport = require('./config/passport') const methodOverride = require('method-override') +const helpers = require('./_helpers') if (process.env.NODE_ENV !== 'production') { require('dotenv').config() } @@ -20,7 +21,7 @@ app.use(passport.session()) app.use(flash()) app.use((req, res, next) => { - res.locals.user = req.user + res.locals.user = helpers.getUser(req) res.locals.success_messages = req.flash('success_messages') res.locals.error_messages = req.flash('error_messages') next() diff --git a/routes/index.js b/routes/index.js index e09002cc..80e9d877 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,19 +1,20 @@ const restController = require('../controllers/restController') const adminController = require('../controllers/adminController.js') const userController = require('../controllers/userController.js') +const helpers = require('../_helpers') const multer = require('multer') const upload = multer({ dest: 'temp/' }) module.exports = (app, passport) => { const authenticated = (req, res, next) => { - if (req.isAuthenticated()) { + if (helpers.ensureAuthenticated(req)) { return next() } res.redirect('/signin') } const authenticatedAdmin = (req, res, next) => { - if (req.isAuthenticated()) { - if (req.user.isAdmin) { return next() } + if (helpers.ensureAuthenticated(req)) { + if (helpers.getUser(req).isAdmin) { return next() } return res.redirect('/') } res.redirect('/signin') From 2c530496239584025b3d9798dff5b83d2083eb90 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Sat, 20 Nov 2021 23:17:35 +0800 Subject: [PATCH 064/101] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E7=80=8F?= =?UTF-8?q?=E8=A6=BD=E6=89=80=E6=9C=89=E4=BD=BF=E7=94=A8=E8=80=85=E9=A0=81?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 3 +- controllers/adminController.js | 6 ++ helpers/handlebarsHelpers.js | 10 +++ package-lock.json | 98 +++++++++++++++++++++++++----- package.json | 4 +- routes/index.js | 4 ++ views/admin/restaurants.handlebars | 3 + views/admin/users.handlebars | 30 +++++++++ 8 files changed, 140 insertions(+), 18 deletions(-) create mode 100644 helpers/handlebarsHelpers.js create mode 100644 views/admin/users.handlebars diff --git a/app.js b/app.js index 79c8245a..f312111c 100644 --- a/app.js +++ b/app.js @@ -5,13 +5,14 @@ const session = require('express-session') const passport = require('./config/passport') const methodOverride = require('method-override') const helpers = require('./_helpers') +const handlebarsHelpers = require('./helpers/handlebarsHelpers') if (process.env.NODE_ENV !== 'production') { require('dotenv').config() } const app = express() const port = process.env.PORT || 3000 -app.engine('handlebars', exphbs({ defaultLayout: 'main' })) +app.engine('handlebars', exphbs({ defaultLayout: 'main', helpers: handlebarsHelpers })) app.set('view engine', 'handlebars') app.use(methodOverride('_method')) app.use(express.urlencoded({extended: true})) diff --git a/controllers/adminController.js b/controllers/adminController.js index a22effc3..06def585 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -3,6 +3,7 @@ const imgur = require('imgur-node-api') const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID const db = require('../models') const Restaurant = db.Restaurant +const User = db.User const adminController = { getRestaurants: (req, res) => { @@ -122,6 +123,11 @@ const adminController = { res.redirect('/admin/restaurants') }) }) + }, + + getUser: (req, res) => { + return User.findAll({ raw: true, nest: true }) + .then(users => res.render('admin/users', { users })) } } diff --git a/helpers/handlebarsHelpers.js b/helpers/handlebarsHelpers.js new file mode 100644 index 00000000..8a5168e4 --- /dev/null +++ b/helpers/handlebarsHelpers.js @@ -0,0 +1,10 @@ +module.exports = { + showRole: function (isAdmin) { + if (isAdmin) return 'admin' + return 'user' + }, + setRole: function (isAdmin) { + if (isAdmin) return 'set as user' + return 'set as admin' + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6458e956..bebc2eb6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { - "name": "forum-express-workspace", - "version": "1.0.0", + "name": "forum-express-grading", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -8,6 +8,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", + "dev": true, "requires": { "type-detect": "4.0.8" } @@ -16,6 +17,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, "requires": { "@sinonjs/commons": "^1.7.0" } @@ -24,6 +26,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", + "dev": true, "requires": { "@sinonjs/commons": "^1", "@sinonjs/samsam": "^5.0.2" @@ -33,6 +36,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.2.0.tgz", "integrity": "sha512-CaIcyX5cDsjcW/ab7HposFWzV1kC++4HNsfnEdFJa7cP1QIuILAKV+BgfeqRXhcnSAc76r/Rh/O5C+300BwUIw==", + "dev": true, "requires": { "@sinonjs/commons": "^1.6.0", "lodash.get": "^4.4.2", @@ -42,7 +46,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==" + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true }, "@types/node": { "version": "14.14.5", @@ -131,7 +136,8 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true }, "aws-sign": { "version": "0.2.0", @@ -357,6 +363,7 @@ "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" } @@ -369,7 +376,8 @@ "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==" + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true }, "concat-map": { "version": "0.0.1", @@ -461,7 +469,8 @@ "cookiejar": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "dev": true }, "core-util-is": { "version": "1.0.3", @@ -509,7 +518,8 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true }, "denque": { "version": "1.4.1", @@ -806,7 +816,18 @@ "fast-safe-stringify": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "dev": true + }, + "fill-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha1-mo+jb06K1jTjv2tPPIiCVRRS6yA=", + "dev": true, + "requires": { + "is-object": "~1.0.1", + "merge-descriptors": "~1.0.0" + } }, "fill-range": { "version": "7.0.1", @@ -852,6 +873,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -861,7 +883,8 @@ "formidable": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "dev": true }, "forwarded": { "version": "0.1.2", @@ -1090,6 +1113,12 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, + "is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -1152,7 +1181,8 @@ "just-extend": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==" + "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", + "dev": true }, "locate-path": { "version": "3.0.0", @@ -1171,7 +1201,8 @@ "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true }, "log-symbols": { "version": "4.0.0", @@ -1374,6 +1405,12 @@ } } }, + "module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha1-z4tP9PKWQGdNbN0CsOO8UjwrvcA=", + "dev": true + }, "moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", @@ -1490,6 +1527,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "dev": true, "requires": { "@sinonjs/commons": "^1.7.0", "@sinonjs/fake-timers": "^6.0.0", @@ -1502,6 +1540,7 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, "requires": { "isarray": "0.0.1" } @@ -1736,6 +1775,17 @@ "ipaddr.js": "1.9.1" } }, + "proxyquire": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", + "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", + "dev": true, + "requires": { + "fill-keys": "^1.0.2", + "module-not-found-error": "^1.0.1", + "resolve": "^1.11.1" + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -1974,6 +2024,17 @@ "yargs": "^13.1.0" } }, + "sequelize-mock": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/sequelize-mock/-/sequelize-mock-0.10.2.tgz", + "integrity": "sha1-GdOXHM2utbhkFwwkznkqinHxRL0=", + "dev": true, + "requires": { + "bluebird": "^3.4.6", + "inflection": "^1.10.0", + "lodash": "^4.16.4" + } + }, "sequelize-pool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", @@ -2017,6 +2078,7 @@ "version": "9.2.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.0.tgz", "integrity": "sha512-eSNXz1XMcGEMHw08NJXSyTHIu6qTCOiN8x9ODACmZpNQpr0aXTBXBnI4xTzQzR+TEpOmLiKowGf9flCuKIzsbw==", + "dev": true, "requires": { "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", @@ -2117,6 +2179,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", + "dev": true, "requires": { "component-emitter": "^1.3.0", "cookiejar": "^2.1.2", @@ -2135,6 +2198,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -2142,17 +2206,20 @@ "mime": { "version": "2.4.6", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "qs": { "version": "6.9.4", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "dev": true } } }, @@ -2160,6 +2227,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/supertest/-/supertest-5.0.0.tgz", "integrity": "sha512-2JAWpPrUOZF4hHH5ZTCN2xjKXvJS3AEwPNXl0HUseHsfcXFvMy9kcsufIHCNAmQ5hlGCvgeAqaR5PBEouN3hlQ==", + "dev": true, "requires": { "methods": "1.1.2", "superagent": "6.1.0" @@ -2429,4 +2497,4 @@ } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 46749e31..b5b9bdb3 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "start": "node app.js", "dev": "nodemon app.js", - "test": "set \"NODE_ENV=test\" && mocha tests --exit --recursive --timeout 5000" + "test": "mocha tests --exit --recursive --timeout 5000" }, "repository": { "type": "git", @@ -41,4 +41,4 @@ "sinon": "^9.2.0", "supertest": "^5.0.0" } -} \ No newline at end of file +} diff --git a/routes/index.js b/routes/index.js index 80e9d877..cc4ff4c5 100644 --- a/routes/index.js +++ b/routes/index.js @@ -35,6 +35,10 @@ module.exports = (app, passport) => { app.put('/admin/restaurants/:id', authenticatedAdmin, upload.single('image'), adminController.putRestaurant) //刪除餐廳資料 app.delete('/admin/restaurants/:id', authenticatedAdmin, adminController.deleteRestaurant) + //顯示使用者清單 + app.get('/admin/users', authenticatedAdmin, adminController.getUser) + //更改使用者權限 + //註冊、登入、登出 app.get('/signup', userController.signUpPage) app.post('/signup', userController.signUp) diff --git a/views/admin/restaurants.handlebars b/views/admin/restaurants.handlebars index 351678bd..2bd2569b 100644 --- a/views/admin/restaurants.handlebars +++ b/views/admin/restaurants.handlebars @@ -1,4 +1,7 @@

    餐廳後台

    + diff --git a/views/admin/users.handlebars b/views/admin/users.handlebars new file mode 100644 index 00000000..aa7860d0 --- /dev/null +++ b/views/admin/users.handlebars @@ -0,0 +1,30 @@ +

    餐廳後台

    +
    + + + + + + + + + + + + {{#each users}} + + + + + + + {{/each}} + +
    #EmailRole#
    {{this.id}}{{this.email}}{{{showRole this.isAdmin}}} + + {{!--
    + +
    --}} +
    \ No newline at end of file From 360412f349fa2ddbf21b5573ae6423a8b225d501 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Mon, 22 Nov 2021 13:20:20 +0800 Subject: [PATCH 065/101] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E6=9B=B4?= =?UTF-8?q?=E6=94=B9=E4=BD=BF=E7=94=A8=E8=80=85=E6=AC=8A=E9=99=90=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/adminController.js | 29 +++++++++++++++++++++++++++-- routes/index.js | 4 ++-- views/admin/users.handlebars | 7 +++---- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/controllers/adminController.js b/controllers/adminController.js index 06def585..3e1b8536 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -125,11 +125,36 @@ const adminController = { }) }, - getUser: (req, res) => { + getUsers: (req, res) => { return User.findAll({ raw: true, nest: true }) .then(users => res.render('admin/users', { users })) + }, + + toggleAdmin: async (req, res) => { + //判斷是否能變更管理權限 (自己不能變更自己) + // if (Number(req.params.id) === req.user.id) { + // req.flash('error_messages','禁止變更管理者權限') + // return res.redirect('/admin/users') + // } + //變更管理權限 + User.findByPk(req.params.id) + .then(async (user) => { + if (user.email === 'root@example.com') { + req.flash('error_messages','禁止變更管理者權限') + return res.redirect('back') + } + user.isAdmin ? await user.update({isAdmin: 0 }) : await user.update({isAdmin: 1 }) + req.flash('success_messages','使用者權限變更成功') + return res.redirect('/admin/users') + }) } } -module.exports = adminController \ No newline at end of file +module.exports = adminController + +// if (user.isAdmin) { +// await user.update({isAdmin: 0 }) +// } else { +// await user.update({isAdmin: 1 }) +// } \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index cc4ff4c5..e6dc7a3f 100644 --- a/routes/index.js +++ b/routes/index.js @@ -36,9 +36,9 @@ module.exports = (app, passport) => { //刪除餐廳資料 app.delete('/admin/restaurants/:id', authenticatedAdmin, adminController.deleteRestaurant) //顯示使用者清單 - app.get('/admin/users', authenticatedAdmin, adminController.getUser) + app.get('/admin/users', authenticatedAdmin, adminController.getUsers) //更改使用者權限 - + app.put('/admin/users/:id/toggleAdmin', authenticatedAdmin, adminController.toggleAdmin) //註冊、登入、登出 app.get('/signup', userController.signUpPage) app.post('/signup', userController.signUp) diff --git a/views/admin/users.handlebars b/views/admin/users.handlebars index aa7860d0..13c3f8df 100644 --- a/views/admin/users.handlebars +++ b/views/admin/users.handlebars @@ -19,10 +19,9 @@ {{this.email}} {{{showRole this.isAdmin}}} - - {{!--
    - -
    --}} +
    + +
    {{/each}} From 935347c51aad7ab7d6f2305287167df5970458ca Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Mon, 22 Nov 2021 23:31:19 +0800 Subject: [PATCH 066/101] =?UTF-8?q?feat:=E8=AA=BF=E6=95=B4=E7=A8=8B?= =?UTF-8?q?=E5=BC=8F=E7=A2=BC=EF=BC=8C=E7=82=BA=E4=BA=86=E8=83=BD=E9=80=9A?= =?UTF-8?q?=E9=81=8E=E6=B8=AC=E8=A9=A6=E6=AA=94=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/adminController.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/adminController.js b/controllers/adminController.js index 3e1b8536..e2cfb592 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -137,13 +137,13 @@ const adminController = { // return res.redirect('/admin/users') // } //變更管理權限 - User.findByPk(req.params.id) + return User.findByPk(req.params.id) .then(async (user) => { if (user.email === 'root@example.com') { req.flash('error_messages','禁止變更管理者權限') return res.redirect('back') } - user.isAdmin ? await user.update({isAdmin: 0 }) : await user.update({isAdmin: 1 }) + user.isAdmin ? await user.update({isAdmin: false }) : await user.update({isAdmin: true }) req.flash('success_messages','使用者權限變更成功') return res.redirect('/admin/users') }) From 7d6f709fa2a6d255cd3d343fd0f859c0836062ba Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 09:28:59 +0800 Subject: [PATCH 067/101] feat:Create category model and add restaurant.CategoryId and association --- migrations/20211122161412-create-category.js | 27 + ...1122161458-add-categoryId-to-restaurant.js | 18 + models/category.js | 23 + models/restaurant.js | 2 +- package-lock.json | 765 ++++++++++++++++++ 5 files changed, 834 insertions(+), 1 deletion(-) create mode 100644 migrations/20211122161412-create-category.js create mode 100644 migrations/20211122161458-add-categoryId-to-restaurant.js create mode 100644 models/category.js diff --git a/migrations/20211122161412-create-category.js b/migrations/20211122161412-create-category.js new file mode 100644 index 00000000..ab0ee89a --- /dev/null +++ b/migrations/20211122161412-create-category.js @@ -0,0 +1,27 @@ +'use strict'; +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Categories', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + name: { + type: Sequelize.STRING + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Categories'); + } +}; \ No newline at end of file diff --git a/migrations/20211122161458-add-categoryId-to-restaurant.js b/migrations/20211122161458-add-categoryId-to-restaurant.js new file mode 100644 index 00000000..70bfc020 --- /dev/null +++ b/migrations/20211122161458-add-categoryId-to-restaurant.js @@ -0,0 +1,18 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.addColumn('Restaurants', 'CategoryId', { + type: Sequelize.INTEGER, + allowNull: true, + references: { + model: 'Categories', + key: 'id' + } + }) + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn('Restaurants', 'CategoryId') + } +}; diff --git a/models/category.js b/models/category.js new file mode 100644 index 00000000..90b0c491 --- /dev/null +++ b/models/category.js @@ -0,0 +1,23 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Category extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + Category.hasMany(models.Restaurant) + } + }; + Category.init({ + name: DataTypes.STRING + }, { + sequelize, + modelName: 'Category', + }); + return Category; +}; \ No newline at end of file diff --git a/models/restaurant.js b/models/restaurant.js index 7ad9a01a..587cf8c4 100644 --- a/models/restaurant.js +++ b/models/restaurant.js @@ -10,7 +10,7 @@ module.exports = (sequelize, DataTypes) => { * The `models/index` file will call this method automatically. */ static associate(models) { - // define association here + Restaurant.belongsTo(models.Category) } }; Restaurant.init({ diff --git a/package-lock.json b/package-lock.json index bebc2eb6..e61e5d01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,11 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + }, "@sinonjs/commons": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", @@ -49,6 +54,14 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, "@types/node": { "version": "14.14.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.5.tgz", @@ -73,6 +86,49 @@ "negotiator": "0.6.2" } }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "requires": { + "string-width": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", @@ -189,6 +245,92 @@ "hoek": "0.7.x" } }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", + "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==" + }, + "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==", + "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==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -253,6 +395,35 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "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" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + } + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -323,6 +494,16 @@ "readdirp": "~3.5.0" } }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" + }, "cli-color": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", @@ -346,6 +527,14 @@ "wrap-ansi": "^5.1.0" } }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "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", @@ -433,6 +622,19 @@ "proto-list": "~1.2.1" } }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, "connect-flash": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", @@ -485,6 +687,11 @@ "boom": "0.3.x" } }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -507,6 +714,14 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -515,6 +730,16 @@ "type-detect": "^4.0.0" } }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -568,6 +793,14 @@ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "requires": { + "is-obj": "^2.0.0" + } + }, "dotenv": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", @@ -578,6 +811,11 @@ "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, "editorconfig": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", @@ -625,6 +863,14 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "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" + } + }, "es5-ext": { "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", @@ -665,6 +911,11 @@ "es6-symbol": "^3.1.1" } }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -940,6 +1191,14 @@ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -961,6 +1220,39 @@ "is-glob": "^4.0.1" } }, + "global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "requires": { + "ini": "2.0.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==" + } + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -996,6 +1288,11 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + }, "hawk": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-0.10.2.tgz", @@ -1017,6 +1314,11 @@ "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.7.6.tgz", "integrity": "sha1-YPvZBFV1Qc0rh5Wr8wihs3cOFVo=" }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -1037,6 +1339,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" + }, "imgur-node-api": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/imgur-node-api/-/imgur-node-api-0.1.0.tgz", @@ -1045,6 +1352,16 @@ "request": "~2.16.6" } }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, "inflection": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", @@ -1082,6 +1399,14 @@ "binary-extensions": "^2.0.0" } }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, "is-core-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz", @@ -1108,17 +1433,41 @@ "is-extglob": "^2.1.1" } }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + }, "is-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", "dev": true }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" + }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -1134,6 +1483,16 @@ "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -1165,6 +1524,11 @@ "esprima": "^4.0.0" } }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, "json-stringify-safe": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-3.0.0.tgz", @@ -1184,6 +1548,22 @@ "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", "dev": true }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "requires": { + "package-json": "^6.3.0" + } + }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -1217,6 +1597,11 @@ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -1233,6 +1618,21 @@ "es5-ext": "~0.10.2" } }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1302,6 +1702,11 @@ "mime-db": "1.44.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", @@ -1547,6 +1952,102 @@ } } }, + "nodemon": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.15.tgz", + "integrity": "sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==", + "requires": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5", + "update-notifier": "^5.1.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "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" + } + } + } + }, "nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -1560,6 +2061,11 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" + }, "oauth-sign": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.2.0.tgz", @@ -1591,6 +2097,11 @@ "wrappy": "1" } }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -1612,6 +2123,24 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "packet-reader": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", @@ -1756,6 +2285,11 @@ "xtend": "^4.0.0" } }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -1791,6 +2325,28 @@ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "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" + } + }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "requires": { + "escape-goat": "^2.0.0" + } + }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", @@ -1825,6 +2381,24 @@ "unpipe": "1.0.0" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "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=" + } + } + }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -1843,6 +2417,22 @@ "picomatch": "^2.2.1" } }, + "registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "requires": { + "rc": "^1.2.8" + } + }, "request": { "version": "2.16.6", "resolved": "https://registry.npmjs.org/request/-/request-2.16.6.tgz", @@ -1920,6 +2510,14 @@ "path-parse": "^1.0.6" } }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "retry-as-promised": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", @@ -1943,6 +2541,21 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -2074,6 +2687,11 @@ "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" }, + "signal-exit": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" + }, "sinon": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.0.tgz", @@ -2250,6 +2868,11 @@ "next-tick": "1" } }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2268,6 +2891,24 @@ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1" + } + } + } + }, "tunnel-agent": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.2.0.tgz", @@ -2283,6 +2924,11 @@ "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==" + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -2297,6 +2943,14 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, "uglify-js": { "version": "3.14.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", @@ -2319,6 +2973,19 @@ "bluebird": "^3.7.2" } }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -2329,6 +2996,45 @@ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "requires": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2399,6 +3105,49 @@ } } }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "requires": { + "string-width": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "wkx": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", @@ -2432,6 +3181,22 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", From a4bc57c35847d119596a0fe3f3883b037720fce8 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 10:07:28 +0800 Subject: [PATCH 068/101] heroku PG switch to ClearDB mysql --- config/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.json b/config/config.json index de5a1af4..e13f7865 100644 --- a/config/config.json +++ b/config/config.json @@ -7,7 +7,7 @@ "dialect": "mysql" }, "production": { - "use_env_variable": "DATABASE_URL", + "use_env_variable": "CLEARDB_DATABASE_URL", "dialect": "postgres", "protocol": "postgres", "dialectOptions": { From 97c7146508c4b34fbbe360f8127a68630770663c Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 10:26:07 +0800 Subject: [PATCH 069/101] feat:Add category seed data --- controllers/adminController.js | 6 ------ ...1122161458-add-categoryId-to-restaurant.js | 2 +- .../20211123021738-categories-seed-file.js | 20 +++++++++++++++++++ ...> 20211123022458-restaurants-seed-file.js} | 3 ++- 4 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 seeders/20211123021738-categories-seed-file.js rename seeders/{20211119152133-restaurants-seed-file.js => 20211123022458-restaurants-seed-file.js} (88%) diff --git a/controllers/adminController.js b/controllers/adminController.js index e2cfb592..7d352a0b 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -152,9 +152,3 @@ const adminController = { module.exports = adminController - -// if (user.isAdmin) { -// await user.update({isAdmin: 0 }) -// } else { -// await user.update({isAdmin: 1 }) -// } \ No newline at end of file diff --git a/migrations/20211122161458-add-categoryId-to-restaurant.js b/migrations/20211122161458-add-categoryId-to-restaurant.js index 70bfc020..661f8700 100644 --- a/migrations/20211122161458-add-categoryId-to-restaurant.js +++ b/migrations/20211122161458-add-categoryId-to-restaurant.js @@ -4,7 +4,7 @@ module.exports = { up: async (queryInterface, Sequelize) => { await queryInterface.addColumn('Restaurants', 'CategoryId', { type: Sequelize.INTEGER, - allowNull: true, + allowNull: false, references: { model: 'Categories', key: 'id' diff --git a/seeders/20211123021738-categories-seed-file.js b/seeders/20211123021738-categories-seed-file.js new file mode 100644 index 00000000..a393ef24 --- /dev/null +++ b/seeders/20211123021738-categories-seed-file.js @@ -0,0 +1,20 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.bulkInsert('Categories', + ['中式料理', '日本料理', '義大利料理', '墨西哥料理', '素食料理', '美式料理', '複合式料理'] + .map((item, index) => + ({ + id: index * 10 + 1, + name: item, + createdAt: new Date(), + updatedAt: new Date() + }) + ), {}) + }, + + down: async (queryInterface, Sequelize) => { + queryInterface.bulkDelete('Categories', null, {}) + } +}; diff --git a/seeders/20211119152133-restaurants-seed-file.js b/seeders/20211123022458-restaurants-seed-file.js similarity index 88% rename from seeders/20211119152133-restaurants-seed-file.js rename to seeders/20211123022458-restaurants-seed-file.js index fccf46e2..5d027673 100644 --- a/seeders/20211119152133-restaurants-seed-file.js +++ b/seeders/20211123022458-restaurants-seed-file.js @@ -13,7 +13,8 @@ module.exports = { image: `https://loremflickr.com/320/240/restaurant,food/?random=${Math.random() * 100}`, description: faker.lorem.text(), createdAt: new Date(), - updatedAt: new Date() + updatedAt: new Date(), + CategoryId: Math.floor(Math.random() * 6) * 10 + 1 }) ), {}) }, From 13384e261bdd2131fee87c973c07373fb9ced8c0 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 10:59:45 +0800 Subject: [PATCH 070/101] feat:Show category name --- controllers/adminController.js | 13 ++++++++++--- views/admin/restaurant.handlebars | 1 + views/admin/restaurants.handlebars | 2 ++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/controllers/adminController.js b/controllers/adminController.js index 7d352a0b..7364ce0a 100644 --- a/controllers/adminController.js +++ b/controllers/adminController.js @@ -4,10 +4,15 @@ const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID const db = require('../models') const Restaurant = db.Restaurant const User = db.User +const Category = db.Category const adminController = { getRestaurants: (req, res) => { - return Restaurant.findAll({raw: true, nest: true}) + return Restaurant.findAll({ + raw: true, + nest: true, + include: [Category] + }) .then(restaurants => { return res.render('admin/restaurants', { restaurants }) }) @@ -56,9 +61,11 @@ const adminController = { }, getRestaurant: (req, res) => { - return Restaurant.findByPk(req.params.id, {raw:true}) + return Restaurant.findByPk(req.params.id, { + include: [Category] + }) .then(restaurant => { - return res.render('admin/restaurant', { restaurant }) + return res.render('admin/restaurant', { restaurant: restaurant.toJSON() }) }) }, diff --git a/views/admin/restaurant.handlebars b/views/admin/restaurant.handlebars index e6b1fa59..b5d1c3cf 100644 --- a/views/admin/restaurant.handlebars +++ b/views/admin/restaurant.handlebars @@ -1,6 +1,7 @@

    {{restaurant.name}}

    +

    {{restaurant.Category.name}}

    diff --git a/views/admin/restaurants.handlebars b/views/admin/restaurants.handlebars index 2bd2569b..c887f7f2 100644 --- a/views/admin/restaurants.handlebars +++ b/views/admin/restaurants.handlebars @@ -15,6 +15,7 @@ # Name + Category # @@ -23,6 +24,7 @@ {{this.id}} {{this.name}} + {{this.Category.name}}
    +
    + + +
    +
    From 829b6ce097ec720788e1377e50b5d40ae0cba67c Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 11:21:16 +0800 Subject: [PATCH 072/101] feat:Update category select in edit page using ifCond-helper --- helpers/handlebarsHelpers.js | 3 +++ views/admin/create.handlebars | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/helpers/handlebarsHelpers.js b/helpers/handlebarsHelpers.js index 8a5168e4..f97db280 100644 --- a/helpers/handlebarsHelpers.js +++ b/helpers/handlebarsHelpers.js @@ -6,5 +6,8 @@ module.exports = { setRole: function (isAdmin) { if (isAdmin) return 'set as user' return 'set as admin' + }, + ifCond: function (a, b) { + if (a === b) return 'selected' } } \ No newline at end of file diff --git a/views/admin/create.handlebars b/views/admin/create.handlebars index 8912e154..2c6403ae 100644 --- a/views/admin/create.handlebars +++ b/views/admin/create.handlebars @@ -12,7 +12,7 @@
    From cb4cc7480bc0c77d0bf6f34d09c66d7166baf391 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 11:40:20 +0800 Subject: [PATCH 073/101] feat:Add admin categories page --- controllers/categoryController.js | 13 +++++++++ routes/index.js | 3 ++ views/admin/categories.handlebars | 45 ++++++++++++++++++++++++++++++ views/admin/restaurants.handlebars | 4 ++- views/admin/users.handlebars | 4 ++- 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 controllers/categoryController.js create mode 100644 views/admin/categories.handlebars diff --git a/controllers/categoryController.js b/controllers/categoryController.js new file mode 100644 index 00000000..ee8913f7 --- /dev/null +++ b/controllers/categoryController.js @@ -0,0 +1,13 @@ +const db = require('../models') +const Category = db.Category +let categoryController = { + getCategories: (req, res) => { + return Category.findAll({ + raw: true, + nest: true + }).then(categories => { + return res.render('admin/categories', { categories }) + }) + } +} +module.exports = categoryController \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index e6dc7a3f..823c504b 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,6 +1,7 @@ const restController = require('../controllers/restController') const adminController = require('../controllers/adminController.js') const userController = require('../controllers/userController.js') +const categoryController = require('../controllers/categoryController.js') const helpers = require('../_helpers') const multer = require('multer') const upload = multer({ dest: 'temp/' }) @@ -45,4 +46,6 @@ module.exports = (app, passport) => { app.get('/signin', userController.signInPage) app.post('/signin', passport.authenticate('local', { failureRedirect: '/signin', failureFlash: true }), userController.signIn) app.get('/logout', userController.logout) + //餐廳分類 + app.get('/admin/categories', authenticatedAdmin, categoryController.getCategories) } diff --git a/views/admin/categories.handlebars b/views/admin/categories.handlebars new file mode 100644 index 00000000..65359572 --- /dev/null +++ b/views/admin/categories.handlebars @@ -0,0 +1,45 @@ +

    餐廳後台

    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + + + + + + + + + {{#each categories}} + + + + + + {{/each}} + +
    #Category Name#
    {{this.id}}{{this.name}} + +
    + +
    +
    +
    +
    \ No newline at end of file diff --git a/views/admin/restaurants.handlebars b/views/admin/restaurants.handlebars index c887f7f2..de19552d 100644 --- a/views/admin/restaurants.handlebars +++ b/views/admin/restaurants.handlebars @@ -1,6 +1,8 @@

    餐廳後台

    diff --git a/views/admin/users.handlebars b/views/admin/users.handlebars index 13c3f8df..3119428a 100644 --- a/views/admin/users.handlebars +++ b/views/admin/users.handlebars @@ -1,6 +1,8 @@

    餐廳後台

    From b3d6b4cca4c9ad4678ce2788e9f65e58715e74c0 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 11:50:29 +0800 Subject: [PATCH 074/101] feat:Add admin categories post feature --- controllers/categoryController.js | 13 +++++++++++++ routes/index.js | 1 + 2 files changed, 14 insertions(+) diff --git a/controllers/categoryController.js b/controllers/categoryController.js index ee8913f7..871820c2 100644 --- a/controllers/categoryController.js +++ b/controllers/categoryController.js @@ -8,6 +8,19 @@ let categoryController = { }).then(categories => { return res.render('admin/categories', { categories }) }) + }, + postCategory: (req, res) => { + if (!req.body.name) { + req.flash('error_messages', 'name didn\'t exist') + return res.redirect('back') + } else { + return Category.create({ + name: req.body.name + }) + .then((category) => { + res.redirect('/admin/categories') + }) + } } } module.exports = categoryController \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 823c504b..ae11d0a5 100644 --- a/routes/index.js +++ b/routes/index.js @@ -48,4 +48,5 @@ module.exports = (app, passport) => { app.get('/logout', userController.logout) //餐廳分類 app.get('/admin/categories', authenticatedAdmin, categoryController.getCategories) + app.post('/admin/categories', authenticatedAdmin, categoryController.postCategory) } From 45fbdd68c5925c4c84d0bcc1575ba8ae323a34a1 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 12:08:40 +0800 Subject: [PATCH 075/101] feat:Add admin categories edit and put feature --- controllers/categoryController.js | 28 ++++++++++++++++++++++++++-- routes/index.js | 2 ++ views/admin/categories.handlebars | 16 ++++++++++++---- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/controllers/categoryController.js b/controllers/categoryController.js index 871820c2..a82b323d 100644 --- a/controllers/categoryController.js +++ b/controllers/categoryController.js @@ -2,11 +2,21 @@ const db = require('../models') const Category = db.Category let categoryController = { getCategories: (req, res) => { - return Category.findAll({ + return Category.findAll({ raw: true, nest: true }).then(categories => { - return res.render('admin/categories', { categories }) + if (req.params.id) { + Category.findByPk(req.params.id) + .then((category) => { + return res.render('admin/categories', { + categories: categories, + category: category.toJSON() + }) + }) + } else { + return res.render('admin/categories', { categories: categories }) + } }) }, postCategory: (req, res) => { @@ -21,6 +31,20 @@ let categoryController = { res.redirect('/admin/categories') }) } + }, + putCategory: (req, res) => { + if (!req.body.name) { + req.flash('error_messages', 'name didn\'t exist') + return res.redirect('back') + } else { + return Category.findByPk(req.params.id) + .then((category) => { + category.update(req.body) + .then((category) => { + res.redirect('/admin/categories') + }) + }) + } } } module.exports = categoryController \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index ae11d0a5..ba4abae3 100644 --- a/routes/index.js +++ b/routes/index.js @@ -49,4 +49,6 @@ module.exports = (app, passport) => { //餐廳分類 app.get('/admin/categories', authenticatedAdmin, categoryController.getCategories) app.post('/admin/categories', authenticatedAdmin, categoryController.postCategory) + app.get('/admin/categories/:id', authenticatedAdmin, categoryController.getCategories) + app.put('/admin/categories/:id', authenticatedAdmin, categoryController.putCategory) } diff --git a/views/admin/categories.handlebars b/views/admin/categories.handlebars index 65359572..b2aca9c1 100644 --- a/views/admin/categories.handlebars +++ b/views/admin/categories.handlebars @@ -7,10 +7,18 @@

    -
    - - - +{{#if category}} +
    + + + or Create New + + {{else}} +
    + + + + {{/if}}


    From 0b1247b300759b407c5b2e13128455b78ad8cd18 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 12:13:54 +0800 Subject: [PATCH 076/101] feat:Add admin categories delete feature --- controllers/categoryController.js | 9 +++++++++ routes/index.js | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/controllers/categoryController.js b/controllers/categoryController.js index a82b323d..e8e25af5 100644 --- a/controllers/categoryController.js +++ b/controllers/categoryController.js @@ -45,6 +45,15 @@ let categoryController = { }) }) } + }, + deleteCategory: (req, res) => { + return Category.findByPk(req.params.id) + .then((category) => { + category.destroy() + .then((category) => { + res.redirect('/admin/categories') + }) + }) } } module.exports = categoryController \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index ba4abae3..e2c17373 100644 --- a/routes/index.js +++ b/routes/index.js @@ -46,9 +46,10 @@ module.exports = (app, passport) => { app.get('/signin', userController.signInPage) app.post('/signin', passport.authenticate('local', { failureRedirect: '/signin', failureFlash: true }), userController.signIn) app.get('/logout', userController.logout) - //餐廳分類 + //餐廳分類CRUD app.get('/admin/categories', authenticatedAdmin, categoryController.getCategories) app.post('/admin/categories', authenticatedAdmin, categoryController.postCategory) app.get('/admin/categories/:id', authenticatedAdmin, categoryController.getCategories) app.put('/admin/categories/:id', authenticatedAdmin, categoryController.putCategory) + app.delete('/admin/categories/:id', authenticatedAdmin, categoryController.deleteCategory) } From 8e33854f78aad7fcf432b4a2dc439fa0b7300558 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 23:17:21 +0800 Subject: [PATCH 077/101] feat:Add restaurants index page --- controllers/restController.js | 22 +++++++++++++++++++--- views/restaurants.handlebars | 23 ++++++++++++++++++++--- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/controllers/restController.js b/controllers/restController.js index d827c187..a44a6ac0 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -1,6 +1,22 @@ +const db = require('../models') +const Restaurant = db.Restaurant +const Category = db.Category + const restController = { - getRestaurants: (req, res) => { - return res.render('restaurants') - } + getRestaurants: (req, res) => { + Restaurant.findAll({ include: Category }) + .then(restaurants => { + console.log(restaurants) + const data = restaurants.map(r => ({ + ...r.dataValues, + description: r.dataValues.description.substring(0, 50), + categoryName: r.Category.name + })) + return res.render('restaurants', { + restaurants: data + }) + }) + } } + module.exports = restController \ No newline at end of file diff --git a/views/restaurants.handlebars b/views/restaurants.handlebars index 97b6e76e..22b57d50 100644 --- a/views/restaurants.handlebars +++ b/views/restaurants.handlebars @@ -1,3 +1,20 @@ -
    - restaurants -
    \ No newline at end of file +
    + {{#each restaurants}} +
    +
    + Card image cap +
    +

    + + {{this.name}} + +

    + {{this.categoryName}} +

    {{this.description}}

    +
    +
    +
    + {{/each}} +
    +
    +
    \ No newline at end of file From 1e2cc274779b91cd5949533eee8ef84a5eee9dfb Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 23:21:25 +0800 Subject: [PATCH 078/101] feat:Add restaurants show page --- controllers/restController.js | 11 ++++++++++- routes/index.js | 2 ++ views/restaurant.handlebars | 23 +++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 views/restaurant.handlebars diff --git a/controllers/restController.js b/controllers/restController.js index a44a6ac0..c4c1652a 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -16,7 +16,16 @@ const restController = { restaurants: data }) }) - } + }, + getRestaurant: (req, res) => { + return Restaurant.findByPk(req.params.id, { + include: Category + }).then(restaurant => { + return res.render('restaurant', { + restaurant: restaurant.toJSON() + }) + }) + } } module.exports = restController \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index e2c17373..5a317d50 100644 --- a/routes/index.js +++ b/routes/index.js @@ -23,6 +23,8 @@ module.exports = (app, passport) => { //瀏覽首頁 app.get('/', authenticated, (req, res) => res.redirect('/restaurants')) app.get('/restaurants', authenticated,restController.getRestaurants) + //使用者瀏覽畫面 + app.get('/restaurants/:id', authenticated, restController.getRestaurant) //瀏覽後台 app.get('/admin', authenticatedAdmin,(req, res) => res.redirect('/admin/restaurants')) app.get('/admin/restaurants', authenticatedAdmin, adminController.getRestaurants) diff --git a/views/restaurant.handlebars b/views/restaurant.handlebars new file mode 100644 index 00000000..67543990 --- /dev/null +++ b/views/restaurant.handlebars @@ -0,0 +1,23 @@ +
    +
    +

    {{restaurant.name}}

    +

    [{{restaurant.Category.name}}]

    +
    +
    + +
    +
      +
    • Opening Hour: {{restaurant.opening_hours}}
    • +
    • Tel: {{restaurant.tel}}
    • +
    • Address: {{restaurant.address}}
    • +
    +
    +
    +
    +

    {{restaurant.description}}

    +
    +
    +
    +
    +
    +回上一頁 \ No newline at end of file From 2d65b6eb67d66abc613d0643763655f92d9e2e9c Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Tue, 23 Nov 2021 23:50:07 +0800 Subject: [PATCH 079/101] feat:Add categories navbar on restaurants index page --- controllers/restController.js | 21 +++++++++++++++++---- helpers/handlebarsHelpers.js | 7 +++++-- views/admin/create.handlebars | 20 ++++++++++++-------- views/restaurants.handlebars | 13 +++++++++++++ 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/controllers/restController.js b/controllers/restController.js index c4c1652a..7fa36dce 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -4,16 +4,29 @@ const Category = db.Category const restController = { getRestaurants: (req, res) => { - Restaurant.findAll({ include: Category }) + const whereQuery = {} + let categoryId = '' + if (req.query.categoryId) { + categoryId = Number(req.query.categoryId) + whereQuery.CategoryId = categoryId + } + Restaurant.findAll({ include: Category, where: whereQuery }) .then(restaurants => { - console.log(restaurants) const data = restaurants.map(r => ({ ...r.dataValues, description: r.dataValues.description.substring(0, 50), categoryName: r.Category.name })) - return res.render('restaurants', { - restaurants: data + Category.findAll({ + raw: true, + nest: true + }) + .then(categories => { // 取出 categoies + return res.render('restaurants', { + restaurants: data, + categories, + categoryId + }) }) }) }, diff --git a/helpers/handlebarsHelpers.js b/helpers/handlebarsHelpers.js index f97db280..527b4d16 100644 --- a/helpers/handlebarsHelpers.js +++ b/helpers/handlebarsHelpers.js @@ -7,7 +7,10 @@ module.exports = { if (isAdmin) return 'set as user' return 'set as admin' }, - ifCond: function (a, b) { - if (a === b) return 'selected' + ifCond: function (a, b, options) { + if (a === b) { + return options.fn(this) + } + return options.inverse(this) } } \ No newline at end of file diff --git a/views/admin/create.handlebars b/views/admin/create.handlebars index 2c6403ae..8967b419 100644 --- a/views/admin/create.handlebars +++ b/views/admin/create.handlebars @@ -8,14 +8,18 @@ -
    - - -
    +
    + + +
    >
    diff --git a/views/restaurants.handlebars b/views/restaurants.handlebars index 22b57d50..f4cecbe8 100644 --- a/views/restaurants.handlebars +++ b/views/restaurants.handlebars @@ -1,3 +1,16 @@ + +
    + +
    {{#each restaurants}}
    From a5caf4ddba49099b017e3bcb7ce8d3ce540cf817 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Wed, 24 Nov 2021 22:44:08 +0800 Subject: [PATCH 080/101] feat:Add pagination on restaurants index --- controllers/restController.js | 53 ++++++++++++++++++++++++----------- views/restaurants.handlebars | 24 +++++++++++++++- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/controllers/restController.js b/controllers/restController.js index 7fa36dce..36f62fe9 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -2,43 +2,64 @@ const db = require('../models') const Restaurant = db.Restaurant const Category = db.Category +const pageLimit = 10 + const restController = { getRestaurants: (req, res) => { + let offset = 0 const whereQuery = {} let categoryId = '' + if (req.query.page) { + offset = (req.query.page - 1) * pageLimit + } if (req.query.categoryId) { categoryId = Number(req.query.categoryId) - whereQuery.CategoryId = categoryId + whereQuery.categoryId = categoryId } - Restaurant.findAll({ include: Category, where: whereQuery }) - .then(restaurants => { - const data = restaurants.map(r => ({ + Restaurant.findAndCountAll({ + include: Category, + where: whereQuery, + offset: offset, + limit: pageLimit + }).then(result => { + // data for pagination + const page = Number(req.query.page) || 1 + const pages = Math.ceil(result.count / pageLimit) + const totalPage = Array.from({ length: pages }).map((item, index) => index + 1) + const prev = page - 1 < 1 ? 1 : page - 1 + const next = page + 1 > pages ? pages : page + 1 + + // clean up restaurant data + const data = result.rows.map(r => ({ ...r.dataValues, description: r.dataValues.description.substring(0, 50), - categoryName: r.Category.name + categoryName: r.dataValues.Category.name })) - Category.findAll({ + Category.findAll({ raw: true, nest: true - }) - .then(categories => { // 取出 categoies + }).then(categories => { return res.render('restaurants', { restaurants: data, - categories, - categoryId + categories: categories, + categoryId: categoryId, + page: page, + totalPage: totalPage, + prev: prev, + next: next }) }) }) }, getRestaurant: (req, res) => { return Restaurant.findByPk(req.params.id, { - include: Category - }).then(restaurant => { - return res.render('restaurant', { - restaurant: restaurant.toJSON() - }) + include: Category + }).then(restaurant => { + return res.render('restaurant', { + restaurant: restaurant.toJSON() }) - } + }) + } } module.exports = restController \ No newline at end of file diff --git a/views/restaurants.handlebars b/views/restaurants.handlebars index f4cecbe8..774019ba 100644 --- a/views/restaurants.handlebars +++ b/views/restaurants.handlebars @@ -30,4 +30,26 @@ {{/each}}

    -
    \ No newline at end of file +
    + + \ No newline at end of file From 1a1b3cdf957d1902a43ed372ce239667300b5210 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Wed, 24 Nov 2021 22:55:19 +0800 Subject: [PATCH 081/101] feat:Create comment model & add association among users, comment, restaurants --- migrations/20211124144738-create-comment.js | 33 +++++++++++++++++++++ models/comment.js | 26 ++++++++++++++++ models/restaurant.js | 1 + models/user.js | 2 +- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 migrations/20211124144738-create-comment.js create mode 100644 models/comment.js diff --git a/migrations/20211124144738-create-comment.js b/migrations/20211124144738-create-comment.js new file mode 100644 index 00000000..8e42b57c --- /dev/null +++ b/migrations/20211124144738-create-comment.js @@ -0,0 +1,33 @@ +'use strict'; +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Comments', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + text: { + type: Sequelize.STRING + }, + UserId: { + type: Sequelize.INTEGER + }, + RestaurantId: { + type: Sequelize.INTEGER + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Comments'); + } +}; \ No newline at end of file diff --git a/models/comment.js b/models/comment.js new file mode 100644 index 00000000..41b4ca37 --- /dev/null +++ b/models/comment.js @@ -0,0 +1,26 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Comment extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + Comment.belongsTo(models.Restaurant) + Comment.belongsTo(models.User) + } + }; + Comment.init({ + text: DataTypes.STRING, + UserId: DataTypes.INTEGER, + RestaurantId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'Comment', + }); + return Comment; +}; \ No newline at end of file diff --git a/models/restaurant.js b/models/restaurant.js index 587cf8c4..8a291713 100644 --- a/models/restaurant.js +++ b/models/restaurant.js @@ -11,6 +11,7 @@ module.exports = (sequelize, DataTypes) => { */ static associate(models) { Restaurant.belongsTo(models.Category) + Restaurant.hasMany(models.comment) } }; Restaurant.init({ diff --git a/models/user.js b/models/user.js index 7f949fd6..483f76c2 100644 --- a/models/user.js +++ b/models/user.js @@ -10,7 +10,7 @@ module.exports = (sequelize, DataTypes) => { * The `models/index` file will call this method automatically. */ static associate(models) { - // define association here + User.hasMany(models.comment) } }; User.init({ From d0695dbfca46819f312ec254bfe748c3f3b6278d Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Wed, 24 Nov 2021 23:05:05 +0800 Subject: [PATCH 082/101] feat:Add post comment feature on restaurant page --- controllers/commentController.js | 17 +++++++++++++++++ models/restaurant.js | 2 +- models/user.js | 2 +- routes/index.js | 6 ++++-- views/restaurant.handlebars | 9 +++++++++ 5 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 controllers/commentController.js diff --git a/controllers/commentController.js b/controllers/commentController.js new file mode 100644 index 00000000..b30fe043 --- /dev/null +++ b/controllers/commentController.js @@ -0,0 +1,17 @@ +const db = require('../models') +const Comment = db.Comment + +const commentController = { + postComment: (req, res) => { + return Comment.create({ + text: req.body.text, + RestaurantId: req.body.restaurantId, + UserId: req.user.id + }) + .then((comment) => { + res.redirect(`/restaurants/${req.body.restaurantId}`) + }) + } +} + +module.exports = commentController \ No newline at end of file diff --git a/models/restaurant.js b/models/restaurant.js index 8a291713..ab74a58f 100644 --- a/models/restaurant.js +++ b/models/restaurant.js @@ -11,7 +11,7 @@ module.exports = (sequelize, DataTypes) => { */ static associate(models) { Restaurant.belongsTo(models.Category) - Restaurant.hasMany(models.comment) + Restaurant.hasMany(models.Comment) } }; Restaurant.init({ diff --git a/models/user.js b/models/user.js index 483f76c2..af4e903e 100644 --- a/models/user.js +++ b/models/user.js @@ -10,7 +10,7 @@ module.exports = (sequelize, DataTypes) => { * The `models/index` file will call this method automatically. */ static associate(models) { - User.hasMany(models.comment) + User.hasMany(models.Comment) } }; User.init({ diff --git a/routes/index.js b/routes/index.js index 5a317d50..e4460b6d 100644 --- a/routes/index.js +++ b/routes/index.js @@ -2,6 +2,7 @@ const restController = require('../controllers/restController') const adminController = require('../controllers/adminController.js') const userController = require('../controllers/userController.js') const categoryController = require('../controllers/categoryController.js') +const commentController = require('../controllers/commentController.js') const helpers = require('../_helpers') const multer = require('multer') const upload = multer({ dest: 'temp/' }) @@ -20,10 +21,9 @@ module.exports = (app, passport) => { } res.redirect('/signin') } - //瀏覽首頁 + //瀏覽首頁、餐廳資料 app.get('/', authenticated, (req, res) => res.redirect('/restaurants')) app.get('/restaurants', authenticated,restController.getRestaurants) - //使用者瀏覽畫面 app.get('/restaurants/:id', authenticated, restController.getRestaurant) //瀏覽後台 app.get('/admin', authenticatedAdmin,(req, res) => res.redirect('/admin/restaurants')) @@ -54,4 +54,6 @@ module.exports = (app, passport) => { app.get('/admin/categories/:id', authenticatedAdmin, categoryController.getCategories) app.put('/admin/categories/:id', authenticatedAdmin, categoryController.putCategory) app.delete('/admin/categories/:id', authenticatedAdmin, categoryController.deleteCategory) + //評論相關 + app.post('/comments', authenticated, commentController.postComment) } diff --git a/views/restaurant.handlebars b/views/restaurant.handlebars index 67543990..e7e42f87 100644 --- a/views/restaurant.handlebars +++ b/views/restaurant.handlebars @@ -20,4 +20,13 @@


    +
    +
    + + +
    + + + + 回上一頁 \ No newline at end of file From 008cacb17e04d5d3d24228e2d3cf87ca81e5550e Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Wed, 24 Nov 2021 23:27:50 +0800 Subject: [PATCH 083/101] feat:Show related comments on restaurant page --- controllers/restController.js | 7 ++++++- helpers/handlebarsHelpers.js | 5 +++++ package.json | 3 ++- views/restaurant.handlebars | 9 +++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/controllers/restController.js b/controllers/restController.js index 36f62fe9..26675dc5 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -1,6 +1,8 @@ const db = require('../models') const Restaurant = db.Restaurant const Category = db.Category +const Comment = db.Comment +const User = db.User const pageLimit = 10 @@ -53,7 +55,10 @@ const restController = { }, getRestaurant: (req, res) => { return Restaurant.findByPk(req.params.id, { - include: Category + include: [ + Category, + { model: Comment, include: [User] } + ] }).then(restaurant => { return res.render('restaurant', { restaurant: restaurant.toJSON() diff --git a/helpers/handlebarsHelpers.js b/helpers/handlebarsHelpers.js index 527b4d16..db9edb5f 100644 --- a/helpers/handlebarsHelpers.js +++ b/helpers/handlebarsHelpers.js @@ -1,3 +1,5 @@ +const moment = require('moment') + module.exports = { showRole: function (isAdmin) { if (isAdmin) return 'admin' @@ -12,5 +14,8 @@ module.exports = { return options.fn(this) } return options.inverse(this) + }, + moment: function (a) { + return moment(a).fromNow() } } \ No newline at end of file diff --git a/package.json b/package.json index b5b9bdb3..a363d5bc 100644 --- a/package.json +++ b/package.json @@ -24,12 +24,13 @@ "imgur-node-api": "^0.1.0", "method-override": "^3.0.0", "mocha": "^8.2.0", + "moment": "^2.29.1", "multer": "^1.4.3", "mysql2": "^2.2.5", + "nodemon": "^2.0.12", "passport": "^0.5.0", "passport-local": "^1.0.0", "pg": "^8.7.1", - "nodemon": "^2.0.12", "sequelize": "^6.3.5", "sequelize-cli": "^6.2.0" }, diff --git a/views/restaurant.handlebars b/views/restaurant.handlebars index e7e42f87..e906aa5d 100644 --- a/views/restaurant.handlebars +++ b/views/restaurant.handlebars @@ -20,6 +20,15 @@


    +

    所有評論:

    +{{#each restaurant.Comments}} +
    +

    {{this.User.name}}

    +

    {{this.text}}

    +
    {{{moment this.createdAt}}}
    +
    +
    +{{/each}}
    From f128cdd22adec48960bfda06571f73dcfc906c74 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Wed, 24 Nov 2021 23:31:29 +0800 Subject: [PATCH 084/101] feat:Add delete comment feature for admin --- controllers/commentController.js | 9 +++++++++ routes/index.js | 1 + views/restaurant.handlebars | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/controllers/commentController.js b/controllers/commentController.js index b30fe043..68e412c3 100644 --- a/controllers/commentController.js +++ b/controllers/commentController.js @@ -11,6 +11,15 @@ const commentController = { .then((comment) => { res.redirect(`/restaurants/${req.body.restaurantId}`) }) + }, + deleteComment: (req, res) => { + return Comment.findByPk(req.params.id) + .then((comment) => { + comment.destroy() + .then((comment) => { + res.redirect(`/restaurants/${comment.RestaurantId}`) + }) + }) } } diff --git a/routes/index.js b/routes/index.js index e4460b6d..aaac61f5 100644 --- a/routes/index.js +++ b/routes/index.js @@ -56,4 +56,5 @@ module.exports = (app, passport) => { app.delete('/admin/categories/:id', authenticatedAdmin, categoryController.deleteCategory) //評論相關 app.post('/comments', authenticated, commentController.postComment) + app.delete('/comments/:id', authenticatedAdmin, commentController.deleteComment) } diff --git a/views/restaurant.handlebars b/views/restaurant.handlebars index e906aa5d..d28c8456 100644 --- a/views/restaurant.handlebars +++ b/views/restaurant.handlebars @@ -22,6 +22,11 @@

    所有評論:

    {{#each restaurant.Comments}} + {{#if ../user.isAdmin}} + + + + {{/if}}

    {{this.User.name}}

    {{this.text}}

    From c83596ffcc719b799d68b2c6d0b7ed4d586449f0 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Wed, 24 Nov 2021 23:38:50 +0800 Subject: [PATCH 085/101] =?UTF-8?q?=E8=A7=A3=E6=B1=BA=E5=90=88=E4=BD=B5?= =?UTF-8?q?=E8=A1=9D=E7=AA=812?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.json | 8 -------- helpers/unitTestHelpers.js | 6 ------ package-lock.json | 23 ----------------------- 3 files changed, 37 deletions(-) diff --git a/config/config.json b/config/config.json index e28e4e0b..e13f7865 100644 --- a/config/config.json +++ b/config/config.json @@ -7,7 +7,6 @@ "dialect": "mysql" }, "production": { -<<<<<<< HEAD "use_env_variable": "CLEARDB_DATABASE_URL", "dialect": "postgres", "protocol": "postgres", @@ -16,13 +15,6 @@ "rejectUnauthorized": false } } -======= - "username": "root", - "password": null, - "database": "database_production", - "host": "127.0.0.1", - "dialect": "mysql" ->>>>>>> origin/R02-test }, "travis": { "username": "travis", diff --git a/helpers/unitTestHelpers.js b/helpers/unitTestHelpers.js index 90b65faa..4a777f4c 100644 --- a/helpers/unitTestHelpers.js +++ b/helpers/unitTestHelpers.js @@ -33,12 +33,9 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(data.map(d => mockModel.build(d))) } else if (query === 'findAll') { // 回傳模擬資料 -<<<<<<< HEAD if (!data) { return mockModel.build([defaultValue]); } -======= ->>>>>>> origin/R02-test return Promise.resolve( data ? data.map(d => mockModel.build(d)) : []) }else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 @@ -63,12 +60,9 @@ const createModelMock = (name, defaultValue, data, joinedTableName) => { return Promise.resolve(mockModel.build(data)) } else if (query === 'findAll') { // 回傳模擬資料 -<<<<<<< HEAD if (!data) { return mockModel.build([defaultValue]); } -======= ->>>>>>> origin/R02-test return Promise.resolve(data ? data.map(d => mockModel.build(d)) : []) } else if (query === 'destroy') { // destroy 可以從 where 取得要刪除的資料 diff --git a/package-lock.json b/package-lock.json index a39619e1..2d8f3c5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,6 @@ { -<<<<<<< HEAD "name": "forum-express-grading", "version": "2.0.0", -======= - "name": "forum-express-workspace", - "version": "1.0.0", ->>>>>>> origin/R02-test "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1075,7 +1070,6 @@ "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", "dev": true }, -<<<<<<< HEAD "fill-keys": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", @@ -1086,8 +1080,6 @@ "merge-descriptors": "~1.0.0" } }, -======= ->>>>>>> origin/R02-test "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1460,7 +1452,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, -<<<<<<< HEAD "is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", @@ -1477,8 +1468,6 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" }, -======= ->>>>>>> origin/R02-test "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -1821,15 +1810,12 @@ } } }, -<<<<<<< HEAD "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 }, -======= ->>>>>>> origin/R02-test "moment": { "version": "2.29.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", @@ -2323,7 +2309,6 @@ "ipaddr.js": "1.9.1" } }, -<<<<<<< HEAD "proxyquire": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", @@ -2335,8 +2320,6 @@ "resolve": "^1.11.1" } }, -======= ->>>>>>> origin/R02-test "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -2654,7 +2637,6 @@ "yargs": "^13.1.0" } }, -<<<<<<< HEAD "sequelize-mock": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/sequelize-mock/-/sequelize-mock-0.10.2.tgz", @@ -2666,8 +2648,6 @@ "lodash": "^4.16.4" } }, -======= ->>>>>>> origin/R02-test "sequelize-pool": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", @@ -2763,14 +2743,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, -<<<<<<< HEAD "streamsearch": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" }, -======= ->>>>>>> origin/R02-test "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", From a9116e5277977c6a92beb99968c71deda7589625 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 25 Nov 2021 00:12:01 +0800 Subject: [PATCH 086/101] =?UTF-8?q?feat:=E5=BB=BA=E7=AB=8B=E5=80=8B?= =?UTF-8?q?=E4=BA=BA=E8=B3=87=E6=96=99=E9=A0=81=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/userController.js | 4 ++++ routes/index.js | 2 ++ views/profile.handlebars | 10 ++++++++++ 3 files changed, 16 insertions(+) create mode 100644 views/profile.handlebars diff --git a/controllers/userController.js b/controllers/userController.js index b7003660..f310f459 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -45,6 +45,10 @@ const userController = { req.flash('success_messages', '登出成功!') req.logout() res.redirect('/signin') + }, + + getUser: (req, res) => { + return res.render('profile') } } diff --git a/routes/index.js b/routes/index.js index aaac61f5..9d5930ea 100644 --- a/routes/index.js +++ b/routes/index.js @@ -48,6 +48,8 @@ module.exports = (app, passport) => { app.get('/signin', userController.signInPage) app.post('/signin', passport.authenticate('local', { failureRedirect: '/signin', failureFlash: true }), userController.signIn) app.get('/logout', userController.logout) + //使用者個人資料 + app.get('/users/:id', authenticated, userController.getUser) //餐廳分類CRUD app.get('/admin/categories', authenticatedAdmin, categoryController.getCategories) app.post('/admin/categories', authenticatedAdmin, categoryController.postCategory) diff --git a/views/profile.handlebars b/views/profile.handlebars new file mode 100644 index 00000000..0d5e2366 --- /dev/null +++ b/views/profile.handlebars @@ -0,0 +1,10 @@ +
    +
    + +
    +
    + VV +

    VV

    + edit +
    +
    \ No newline at end of file From 8abd6365d5c6af066db14ab11a41e28e79a5819f Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 25 Nov 2021 00:34:20 +0800 Subject: [PATCH 087/101] =?UTF-8?q?feat:=E5=9C=A8=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E8=80=85=E7=9A=84model=E6=96=B0=E5=A2=9E=E7=85=A7=E7=89=87?= =?UTF-8?q?=E6=AC=84=E4=BD=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- migrations/20211124162917-add-image-to-users.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 migrations/20211124162917-add-image-to-users.js diff --git a/migrations/20211124162917-add-image-to-users.js b/migrations/20211124162917-add-image-to-users.js new file mode 100644 index 00000000..d469cffd --- /dev/null +++ b/migrations/20211124162917-add-image-to-users.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.addColumn( 'Users', 'image', { + type: Sequelize.STRING, + defaultValue: 'https://i.epochtimes.com/assets/uploads/2021/08/id13156667-shutterstock_376153318-450x322.jpg' + }); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn( 'Users', 'image' ); + } +}; \ No newline at end of file From 06b420b5eaae7d6b8a9bf688339dfebbbeda95f7 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 25 Nov 2021 09:14:33 +0800 Subject: [PATCH 088/101] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E7=80=8F?= =?UTF-8?q?=E8=A6=BD=E4=BD=BF=E7=94=A8=E8=80=85=E9=A0=81=E9=9D=A2=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=84=A1=E6=B3=95=E5=8F=96?= =?UTF-8?q?=E5=BE=97=E5=80=8B=E4=BA=BA=E5=9C=96=E7=89=87=E8=B3=87=E6=96=99?= =?UTF-8?q?=E7=9A=84=E9=8C=AF=E8=AA=A4=E8=A8=AD=E5=AE=9A(user=20model?= =?UTF-8?q?=E5=85=A7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/userController.js | 3 ++- models/user.js | 3 ++- views/profile.handlebars | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/controllers/userController.js b/controllers/userController.js index f310f459..660e5acc 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -48,7 +48,8 @@ const userController = { }, getUser: (req, res) => { - return res.render('profile') + User.findByPk(req.params.id) + .then(user => res.render('profile', { user: user.toJSON() })) } } diff --git a/models/user.js b/models/user.js index af4e903e..a7e77296 100644 --- a/models/user.js +++ b/models/user.js @@ -17,7 +17,8 @@ module.exports = (sequelize, DataTypes) => { name: DataTypes.STRING, email: DataTypes.STRING, password: DataTypes.STRING, - isAdmin: DataTypes.BOOLEAN + isAdmin: DataTypes.BOOLEAN, + image: DataTypes.STRING }, { sequelize, modelName: 'User', diff --git a/views/profile.handlebars b/views/profile.handlebars index 0d5e2366..09ded734 100644 --- a/views/profile.handlebars +++ b/views/profile.handlebars @@ -1,10 +1,10 @@
    - +
    - VV -

    VV

    - edit + {{ user.name }} +

    {{ user.email }}

    + edit
    \ No newline at end of file From cf375693ddfb4a1ae1b8f66d96f9cc8073906051 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 25 Nov 2021 09:53:29 +0800 Subject: [PATCH 089/101] =?UTF-8?q?feat:=E5=BB=BA=E7=AB=8B=E7=B7=A8?= =?UTF-8?q?=E8=BC=AF=20Profile=20=E9=A0=81=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/userController.js | 7 ++++++- routes/index.js | 1 + views/edit.handlebars | 11 +++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 views/edit.handlebars diff --git a/controllers/userController.js b/controllers/userController.js index 660e5acc..90350ee0 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -48,8 +48,13 @@ const userController = { }, getUser: (req, res) => { - User.findByPk(req.params.id) + return User.findByPk(req.params.id) .then(user => res.render('profile', { user: user.toJSON() })) + }, + + editUser: (req, res) => { + return User.findByPk(req.params.id) + .then(user => res.render('edit', { user: user.toJSON() })) } } diff --git a/routes/index.js b/routes/index.js index 9d5930ea..9ce11c26 100644 --- a/routes/index.js +++ b/routes/index.js @@ -50,6 +50,7 @@ module.exports = (app, passport) => { app.get('/logout', userController.logout) //使用者個人資料 app.get('/users/:id', authenticated, userController.getUser) + app.get('/users/:id/edit', authenticated, userController.editUser) //餐廳分類CRUD app.get('/admin/categories', authenticatedAdmin, categoryController.getCategories) app.post('/admin/categories', authenticatedAdmin, categoryController.postCategory) diff --git a/views/edit.handlebars b/views/edit.handlebars new file mode 100644 index 00000000..88271508 --- /dev/null +++ b/views/edit.handlebars @@ -0,0 +1,11 @@ +
    +
    + + +
    +
    + + +
    + + \ No newline at end of file From 59dbeb3270f7c4f5689bf076915c6a18c68c9032 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 25 Nov 2021 13:56:30 +0800 Subject: [PATCH 090/101] =?UTF-8?q?feat:=E5=AE=8C=E6=88=90=E7=B7=A8?= =?UTF-8?q?=E8=BC=AF=20Profile=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 1 + controllers/userController.js | 120 +++++++++++++++++++++------------- package-lock.json | 2 +- package.json | 2 +- routes/index.js | 1 + views/edit.handlebars | 6 +- 6 files changed, 85 insertions(+), 47 deletions(-) diff --git a/app.js b/app.js index f312111c..4c740ed1 100644 --- a/app.js +++ b/app.js @@ -4,6 +4,7 @@ const flash = require('connect-flash') const session = require('express-session') const passport = require('./config/passport') const methodOverride = require('method-override') +const bodyParser = require('body-parser') const helpers = require('./_helpers') const handlebarsHelpers = require('./helpers/handlebarsHelpers') if (process.env.NODE_ENV !== 'production') { diff --git a/controllers/userController.js b/controllers/userController.js index 90350ee0..f099046a 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -1,61 +1,93 @@ +const imgur = require('imgur-node-api') +const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID const bcrypt = require('bcryptjs') const db = require('../models') const User = db.User const userController = { - signUpPage: (req, res) => { - return res.render('signup') - }, + signUpPage: (req, res) => { + return res.render('signup') + }, - signUp: (req, res) => { - // confirm password - if(req.body.passwordCheck !== req.body.password){ - req.flash('error_messages', '兩次密碼輸入不同!') + signUp: (req, res) => { + // confirm password + if(req.body.passwordCheck !== req.body.password){ + req.flash('error_messages', '兩次密碼輸入不同!') + return res.redirect('/signup') + } else { + // confirm unique user + User.findOne({where: {email: req.body.email}}).then(user => { + if(user){ + req.flash('error_messages', '信箱重複!') return res.redirect('/signup') } else { - // confirm unique user - User.findOne({where: {email: req.body.email}}).then(user => { - if(user){ - req.flash('error_messages', '信箱重複!') - return res.redirect('/signup') - } else { - User.create({ - name: req.body.name, - email: req.body.email, - password: bcrypt.hashSync(req.body.password, bcrypt.genSaltSync(10), null) - }).then(user => { - req.flash('success_messages', '成功註冊帳號!') - return res.redirect('/signin') - }) - } - }) + User.create({ + name: req.body.name, + email: req.body.email, + password: bcrypt.hashSync(req.body.password, bcrypt.genSaltSync(10), null) + }).then(user => { + req.flash('success_messages', '成功註冊帳號!') + return res.redirect('/signin') + }) } - }, + }) + } + }, - signInPage: (req, res) => { - return res.render('signin') - }, + signInPage: (req, res) => { + return res.render('signin') + }, - signIn: (req, res) => { - req.flash('success_messages', '成功登入!') - res.redirect('/restaurants') - }, + signIn: (req, res) => { + req.flash('success_messages', '成功登入!') + res.redirect('/restaurants') + }, - logout: (req, res) => { - req.flash('success_messages', '登出成功!') - req.logout() - res.redirect('/signin') - }, + logout: (req, res) => { + req.flash('success_messages', '登出成功!') + req.logout() + res.redirect('/signin') + }, - getUser: (req, res) => { - return User.findByPk(req.params.id) - .then(user => res.render('profile', { user: user.toJSON() })) - }, + getUser: (req, res) => { + return User.findByPk(req.params.id) + .then(user => res.render('profile', { user: user.toJSON() })) + }, - editUser: (req, res) => { - return User.findByPk(req.params.id) - .then(user => res.render('edit', { user: user.toJSON() })) - } + editUser: (req, res) => { + return User.findByPk(req.params.id) + .then(user => res.render('edit', { user: user.toJSON() })) + }, + + putUser: (req,res) => { + return User.findByPk(req.params.id) + .then(user =>{ + const { file } = req + if (file) { + imgur.setClientID(IMGUR_CLIENT_ID) + imgur.upload(file.path, (err, img) => { + return user.update({ + name: req.body.name, + email: req.body.email, + image: file ? img.data.link : null + }) + .then(()=>{ + req.flash('success_messages','使用者資料編輯成功') + return res.redirect(`/users/${req.params.id}`) + }) + }) + } else { + return user.update({ + name: req.body.name, + email: req.body.email + }) + .then(()=>{ + req.flash('success_messages','使用者資料編輯成功') + return res.redirect(`/users/${req.params.id}`) + }) + } + }) + } } module.exports = userController \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 2d8f3c5e..e61e5d01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3262,4 +3262,4 @@ } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 966c72b8..a363d5bc 100644 --- a/package.json +++ b/package.json @@ -42,4 +42,4 @@ "sinon": "^9.2.0", "supertest": "^5.0.0" } -} \ No newline at end of file +} diff --git a/routes/index.js b/routes/index.js index 9ce11c26..5b7e809d 100644 --- a/routes/index.js +++ b/routes/index.js @@ -51,6 +51,7 @@ module.exports = (app, passport) => { //使用者個人資料 app.get('/users/:id', authenticated, userController.getUser) app.get('/users/:id/edit', authenticated, userController.editUser) + app.put('/users/:id', authenticated, upload.single('image'), userController.putUser) //餐廳分類CRUD app.get('/admin/categories', authenticatedAdmin, categoryController.getCategories) app.post('/admin/categories', authenticatedAdmin, categoryController.postCategory) diff --git a/views/edit.handlebars b/views/edit.handlebars index 88271508..39d2c2b3 100644 --- a/views/edit.handlebars +++ b/views/edit.handlebars @@ -1,7 +1,11 @@
    - + +
    +
    + +
    From 2c16f407b07b473041120ca3d4512086164cc8a7 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Thu, 25 Nov 2021 23:42:25 +0800 Subject: [PATCH 091/101] =?UTF-8?q?=E4=BD=BF=E7=94=A8async/await=E6=94=B9?= =?UTF-8?q?=E5=AF=ABputUser=E5=A4=B1=E6=95=97(=E7=A8=8B=E5=BC=8F=E7=A2=BC?= =?UTF-8?q?=E5=B7=B2=E8=A8=BB=E8=A7=A3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/userController.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/controllers/userController.js b/controllers/userController.js index f099046a..1fb6f8fc 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -58,7 +58,24 @@ const userController = { return User.findByPk(req.params.id) .then(user => res.render('edit', { user: user.toJSON() })) }, - + //使用 async/await 改寫失敗 (圖片無法上傳更新到資料庫內) + // putUser: async (req, res) => { + // const userId = req.params.id + // const userData = await User.findByPk(userId) + // const { file } = req + // if (file) { + // imgur.setClientID(IMGUR_CLIENT_ID) + // await imgur.upload(file.path, (err, img) => { + // return userData.update({ image: img.data.link }) + // }) + // } + // await userData.update({ + // name: req.body.name, + // email: req.body.email + // }) + // await req.flash('success_messages','使用者資料編輯成功') + // return res.redirect(`/users/${userId}`) + // } putUser: (req,res) => { return User.findByPk(req.params.id) .then(user =>{ From 5164db49ab6aeb8a05ac64d03dbf68ad0bc3a886 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Sat, 27 Nov 2021 00:38:30 +0800 Subject: [PATCH 092/101] =?UTF-8?q?feat:=E5=9C=A8=E5=80=8B=E4=BA=BA?= =?UTF-8?q?=E9=A0=81=E9=9D=A2=E9=A1=AF=E7=A4=BA=E8=A9=95=E8=AB=96=E9=81=8E?= =?UTF-8?q?=E7=9A=84=E9=A4=90=E5=BB=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/userController.js | 15 +++++++++++++-- migrations/20211124144738-create-comment.js | 6 ++++-- views/profile.handlebars | 21 +++++++++++++++++---- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/controllers/userController.js b/controllers/userController.js index 1fb6f8fc..33798162 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -3,6 +3,8 @@ const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID const bcrypt = require('bcryptjs') const db = require('../models') const User = db.User +const Comment = db.Comment +const Restaurant = db.Restaurant const userController = { signUpPage: (req, res) => { @@ -50,8 +52,17 @@ const userController = { }, getUser: (req, res) => { - return User.findByPk(req.params.id) - .then(user => res.render('profile', { user: user.toJSON() })) + return User.findByPk(req.params.id, { + include: { model: Comment, include: [Restaurant] } + }) + .then(user =>{ + const restaurants = user.toJSON().Comments.map(item => item.Restaurant) + return res.render('profile', { + user: user.toJSON(), + commentAmount: user.toJSON().Comments.length, + restaurants + }) + }) }, editUser: (req, res) => { diff --git a/migrations/20211124144738-create-comment.js b/migrations/20211124144738-create-comment.js index 8e42b57c..d8d096f6 100644 --- a/migrations/20211124144738-create-comment.js +++ b/migrations/20211124144738-create-comment.js @@ -12,10 +12,12 @@ module.exports = { type: Sequelize.STRING }, UserId: { - type: Sequelize.INTEGER + type: Sequelize.INTEGER, + references: { model: 'Users',  key: 'id' } }, RestaurantId: { - type: Sequelize.INTEGER + type: Sequelize.INTEGER, + references: { model: 'Restaurants',  key: 'id' } }, createdAt: { allowNull: false, diff --git a/views/profile.handlebars b/views/profile.handlebars index 09ded734..ea58b549 100644 --- a/views/profile.handlebars +++ b/views/profile.handlebars @@ -1,10 +1,23 @@
    - +
    -
    - {{ user.name }} +
    +

    {{ user.name }}

    {{ user.email }}

    - edit +

    {{ commentAmount }} 已評論餐廳

    + edit
    +
    +
    +
    + {{ commentAmount }} 已評論餐廳 +
    +
    + {{#each restaurants}} + + + + {{/each}} +
    \ No newline at end of file From 020752e8297bf19f7c5894883139251963fcaeec Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Sat, 27 Nov 2021 01:09:00 +0800 Subject: [PATCH 093/101] feat:Add feeds page --- controllers/restController.js | 23 +++++++++++++++ routes/index.js | 1 + views/feeds.handlebars | 53 +++++++++++++++++++++++++++++++++++ views/restaurants.handlebars | 10 +++++++ 4 files changed, 87 insertions(+) create mode 100644 views/feeds.handlebars diff --git a/controllers/restController.js b/controllers/restController.js index 26675dc5..5304dea3 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -64,6 +64,29 @@ const restController = { restaurant: restaurant.toJSON() }) }) + }, + getFeeds: (req, res) => { + return Promise.all([ + Restaurant.findAll({ + limit: 10, + raw: true, + nest: true, + order: [['createdAt', 'DESC']], + include: [Category] + }), + Comment.findAll({ + limit: 10, + raw: true, + nest: true, + order: [['createdAt', 'DESC']], + include: [User, Restaurant] + }) + ]).then(([restaurants, comments]) => { + return res.render('feeds', { + restaurants: restaurants, + comments: comments + }) + }) } } diff --git a/routes/index.js b/routes/index.js index 5b7e809d..0c57574d 100644 --- a/routes/index.js +++ b/routes/index.js @@ -24,6 +24,7 @@ module.exports = (app, passport) => { //瀏覽首頁、餐廳資料 app.get('/', authenticated, (req, res) => res.redirect('/restaurants')) app.get('/restaurants', authenticated,restController.getRestaurants) + app.get('/restaurants/feeds', authenticated,restController.getFeeds) app.get('/restaurants/:id', authenticated, restController.getRestaurant) //瀏覽後台 app.get('/admin', authenticatedAdmin,(req, res) => res.redirect('/admin/restaurants')) diff --git a/views/feeds.handlebars b/views/feeds.handlebars new file mode 100644 index 00000000..e068942d --- /dev/null +++ b/views/feeds.handlebars @@ -0,0 +1,53 @@ + +

    +

    最新動態

    +
    +
    +
    +
    +
    + 最新餐廳 +
    +
    + {{#each restaurants}} +
    +

    + {{this.name}} + {{this.Category.name}} +

    +

    {{this.description}}

    + {{moment this.createdAt}} +
    +
    + {{/each}} +
    +
    +
    +
    +
    +
    + 最新評論 +
    +
    + {{#each comments}} +
    +

    + {{this.Restaurant.name}} +

    +

    {{this.text}}

    + by {{this.User.name}} + at {{moment this.createdAt}} +
    +
    + {{/each}} +
    +
    +
    +
    \ No newline at end of file diff --git a/views/restaurants.handlebars b/views/restaurants.handlebars index 774019ba..25cf0dbe 100644 --- a/views/restaurants.handlebars +++ b/views/restaurants.handlebars @@ -1,3 +1,13 @@ + +
    +
    - {{ commentAmount }} 已評論餐廳 + {{ user.Comments.length }} 已評論餐廳
    - {{#each restaurants}} - - + {{#each user.Comments}} + + {{/each}}
    From 485c7d024e4f8e75bae1ff01cdaa06bcb676d1b4 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Sat, 27 Nov 2021 22:59:57 +0800 Subject: [PATCH 095/101] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9Edashboard=20?= =?UTF-8?q?=E9=A0=81=E9=9D=A2=E6=9C=83=E5=BD=99=E6=95=B4=E9=A4=90=E5=BB=B3?= =?UTF-8?q?=E8=B3=87=E8=A8=8A(=E5=8F=AF=E9=A1=AF=E7=A4=BA=E8=A9=95?= =?UTF-8?q?=E8=AB=96=E6=95=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/restController.js | 9 +++++++++ routes/index.js | 1 + views/dashboard.handlebars | 15 +++++++++++++++ views/restaurant.handlebars | 1 + 4 files changed, 26 insertions(+) create mode 100644 views/dashboard.handlebars diff --git a/controllers/restController.js b/controllers/restController.js index 5304dea3..0aba8e68 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -87,6 +87,15 @@ const restController = { comments: comments }) }) + }, + getDashBoard: (req, res) => { + return Restaurant.findByPk(req.params.id, { + include: [Comment, Category] + }) + .then(restaurant => { + console.log(restaurant.toJSON()) + return res.render('dashboard', { restaurant: restaurant.toJSON()}) + }) } } diff --git a/routes/index.js b/routes/index.js index 0c57574d..3fc10e8e 100644 --- a/routes/index.js +++ b/routes/index.js @@ -26,6 +26,7 @@ module.exports = (app, passport) => { app.get('/restaurants', authenticated,restController.getRestaurants) app.get('/restaurants/feeds', authenticated,restController.getFeeds) app.get('/restaurants/:id', authenticated, restController.getRestaurant) + app.get('/restaurants/:id/dashboard', authenticated, restController.getDashBoard) //瀏覽後台 app.get('/admin', authenticatedAdmin,(req, res) => res.redirect('/admin/restaurants')) app.get('/admin/restaurants', authenticatedAdmin, adminController.getRestaurants) diff --git a/views/dashboard.handlebars b/views/dashboard.handlebars new file mode 100644 index 00000000..38482a0f --- /dev/null +++ b/views/dashboard.handlebars @@ -0,0 +1,15 @@ +
    +
    +

    {{restaurant.name}}

    +

    [{{restaurant.Category.name}}]

    +
    +
    +
    +
      +
    • 評論數:{{restaurant.Comments.length}}
    • +
    • 瀏覽數:
    • +
    • 收藏數:
    • +
    +
    + 回上一頁 +
    \ No newline at end of file diff --git a/views/restaurant.handlebars b/views/restaurant.handlebars index d28c8456..9ed636f5 100644 --- a/views/restaurant.handlebars +++ b/views/restaurant.handlebars @@ -15,6 +15,7 @@

    {{restaurant.description}}

    + DashBoard

    From 22678a36ec5bb82cbc0787e2c9925760e08afdcf Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Sat, 27 Nov 2021 23:47:32 +0800 Subject: [PATCH 096/101] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E9=A4=90?= =?UTF-8?q?=E5=BB=B3=E8=A8=88=E7=AE=97=E7=80=8F=E8=A6=BD=E6=AC=A1=E6=95=B8?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/restController.js | 10 ++++------ ...20211127150828-add-viewCounts-to-restaurants.js | 14 ++++++++++++++ models/restaurant.js | 3 ++- views/dashboard.handlebars | 2 +- 4 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 migrations/20211127150828-add-viewCounts-to-restaurants.js diff --git a/controllers/restController.js b/controllers/restController.js index 0aba8e68..ab4824d4 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -59,11 +59,10 @@ const restController = { Category, { model: Comment, include: [User] } ] - }).then(restaurant => { - return res.render('restaurant', { - restaurant: restaurant.toJSON() - }) - }) + }).then(restaurant => + restaurant.increment({viewCounts: 1}) + .then(() =>res.render('restaurant', { restaurant: restaurant.toJSON() })) + ) }, getFeeds: (req, res) => { return Promise.all([ @@ -93,7 +92,6 @@ const restController = { include: [Comment, Category] }) .then(restaurant => { - console.log(restaurant.toJSON()) return res.render('dashboard', { restaurant: restaurant.toJSON()}) }) } diff --git a/migrations/20211127150828-add-viewCounts-to-restaurants.js b/migrations/20211127150828-add-viewCounts-to-restaurants.js new file mode 100644 index 00000000..ed49e221 --- /dev/null +++ b/migrations/20211127150828-add-viewCounts-to-restaurants.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.addColumn( 'Restaurants', 'viewCounts', { + type: Sequelize.INTEGER, + defaultValue: 0 + }) + }, + + down: async (queryInterface, Sequelize) => { + await queryInterface.removeColumn( 'Restaurants', 'viewCounts' ); + } +}; diff --git a/models/restaurant.js b/models/restaurant.js index ab74a58f..a7c88e65 100644 --- a/models/restaurant.js +++ b/models/restaurant.js @@ -20,7 +20,8 @@ module.exports = (sequelize, DataTypes) => { address: DataTypes.STRING, opening_hours: DataTypes.STRING, description: DataTypes.TEXT, - image: DataTypes.STRING + image: DataTypes.STRING, + viewCounts: DataTypes.INTEGER }, { sequelize, modelName: 'Restaurant', diff --git a/views/dashboard.handlebars b/views/dashboard.handlebars index 38482a0f..dbe29e00 100644 --- a/views/dashboard.handlebars +++ b/views/dashboard.handlebars @@ -7,7 +7,7 @@
    • 評論數:{{restaurant.Comments.length}}
    • -
    • 瀏覽數:
    • +
    • 瀏覽數:{{restaurant.viewCounts}}
    • 收藏數:
    From c07c01fdb5cb9dafc6aa73590904109ddcbf4a51 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Sun, 28 Nov 2021 00:16:16 +0800 Subject: [PATCH 097/101] feat:Create favorite model and set association between restaurant and user --- migrations/20211127161400-create-favorite.js | 30 ++++++++++++++++++++ models/favorite.js | 24 ++++++++++++++++ models/restaurant.js | 5 ++++ models/user.js | 5 ++++ 4 files changed, 64 insertions(+) create mode 100644 migrations/20211127161400-create-favorite.js create mode 100644 models/favorite.js diff --git a/migrations/20211127161400-create-favorite.js b/migrations/20211127161400-create-favorite.js new file mode 100644 index 00000000..6b9a5748 --- /dev/null +++ b/migrations/20211127161400-create-favorite.js @@ -0,0 +1,30 @@ +'use strict'; +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Favorites', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + UserId: { + type: Sequelize.INTEGER + }, + RestaurantId: { + type: Sequelize.INTEGER + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Favorites'); + } +}; \ No newline at end of file diff --git a/models/favorite.js b/models/favorite.js new file mode 100644 index 00000000..3def4705 --- /dev/null +++ b/models/favorite.js @@ -0,0 +1,24 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Favorite extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + }; + Favorite.init({ + UserId: DataTypes.INTEGER, + RestaurantId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'Favorite', + }); + return Favorite; +}; \ No newline at end of file diff --git a/models/restaurant.js b/models/restaurant.js index a7c88e65..2a0df9fe 100644 --- a/models/restaurant.js +++ b/models/restaurant.js @@ -12,6 +12,11 @@ module.exports = (sequelize, DataTypes) => { static associate(models) { Restaurant.belongsTo(models.Category) Restaurant.hasMany(models.Comment) + Restaurant.belongsToMany(models.User, { + through: models.Favorite, + foreignKey: 'RestaurantId', + as: 'FavoritedUsers' + }) } }; Restaurant.init({ diff --git a/models/user.js b/models/user.js index a7e77296..44d9f0d3 100644 --- a/models/user.js +++ b/models/user.js @@ -11,6 +11,11 @@ module.exports = (sequelize, DataTypes) => { */ static associate(models) { User.hasMany(models.Comment) + User.belongsToMany(models.Restaurant, { + through: models.Favorite, + foreignKey: 'UserId', + as: 'FavoritedRestaurants' + }) } }; User.init({ From a9b8ff29ad6bac1e33c6a973a9b4dfe4c1df6866 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 10 Dec 2021 10:42:17 +0800 Subject: [PATCH 098/101] feat:Add favorite/unfavorite feature --- controllers/userController.js | 24 ++++++++++++++++++++++++ routes/index.js | 3 +++ views/restaurants.handlebars | 2 ++ 3 files changed, 29 insertions(+) diff --git a/controllers/userController.js b/controllers/userController.js index 439246c1..3732fb3e 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -5,6 +5,7 @@ const db = require('../models') const User = db.User const Comment = db.Comment const Restaurant = db.Restaurant +const Favorite = db.Favorite const userController = { signUpPage: (req, res) => { @@ -108,6 +109,29 @@ const userController = { }) } }) + }, + addFavorite: (req, res) => { + return Favorite.create({ + UserId: req.user.id, + RestaurantId: req.params.restaurantId + }) + .then((restaurant) => { + return res.redirect('back') + }) + }, + removeFavorite: (req, res) => { + return Favorite.findOne({ + where: { + UserId: req.user.id, + RestaurantId: req.params.restaurantId + } + }) + .then((favorite) => { + favorite.destroy() + .then((restaurant) => { + return res.redirect('back') + }) + }) } } diff --git a/routes/index.js b/routes/index.js index 3fc10e8e..808f37ca 100644 --- a/routes/index.js +++ b/routes/index.js @@ -63,4 +63,7 @@ module.exports = (app, passport) => { //評論相關 app.post('/comments', authenticated, commentController.postComment) app.delete('/comments/:id', authenticatedAdmin, commentController.deleteComment) + //新增、移除我的最愛 + app.post('/favorite/:restaurantId', authenticated, userController.addFavorite) + app.delete('/favorite/:restaurantId', authenticated, userController.removeFavorite) } diff --git a/views/restaurants.handlebars b/views/restaurants.handlebars index 25cf0dbe..4e1df7a2 100644 --- a/views/restaurants.handlebars +++ b/views/restaurants.handlebars @@ -34,6 +34,8 @@

    {{this.categoryName}}

    {{this.description}}

    + +
    From 963c6735eea07cb5d79f1b11f9dd59aa7ceb3ad1 Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Fri, 10 Dec 2021 11:24:16 +0800 Subject: [PATCH 099/101] feat:Switch add/remove favorite button on restaurants index page and single page --- config/passport.js | 7 ++++++- controllers/restController.js | 16 ++++++++++++---- views/restaurant.handlebars | 5 +++++ views/restaurants.handlebars | 8 ++++++-- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/config/passport.js b/config/passport.js index 2ff44c68..a98d9bdc 100644 --- a/config/passport.js +++ b/config/passport.js @@ -3,6 +3,7 @@ const LocalStrategy = require('passport-local') const bcrypt = require('bcryptjs') const db = require('../models') const User = db.User +const Restaurant = db.Restaurant // setup passport strategy passport.use(new LocalStrategy( @@ -27,7 +28,11 @@ passport.serializeUser((user, cb) => { cb(null, user.id) }) passport.deserializeUser((id, cb) => { - User.findByPk(id).then(user => { + User.findByPk(id,{ + include: [ + { model: Restaurant, as: 'FavoritedRestaurants' } + ] + }).then(user => { user = user.toJSON() // 此處與影片示範不同 return cb(null, user) }) diff --git a/controllers/restController.js b/controllers/restController.js index ab4824d4..35299481 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -35,7 +35,8 @@ const restController = { const data = result.rows.map(r => ({ ...r.dataValues, description: r.dataValues.description.substring(0, 50), - categoryName: r.dataValues.Category.name + categoryName: r.dataValues.Category.name, + isFavorited: req.user.FavoritedRestaurants.map(d => d.id).includes(r.id) })) Category.findAll({ raw: true, @@ -57,11 +58,18 @@ const restController = { return Restaurant.findByPk(req.params.id, { include: [ Category, + { model: User, as: 'FavoritedUsers' }, { model: Comment, include: [User] } ] - }).then(restaurant => - restaurant.increment({viewCounts: 1}) - .then(() =>res.render('restaurant', { restaurant: restaurant.toJSON() })) + }).then(restaurant =>{ + const isFavorited = restaurant.FavoritedUsers.map(d => d.id).includes(req.user.id); + return restaurant.increment({viewCounts: 1}) + .then(() =>res.render('restaurant', { + restaurant: restaurant.toJSON(), + isFavorited + })) + } + ) }, getFeeds: (req, res) => { diff --git a/views/restaurant.handlebars b/views/restaurant.handlebars index 9ed636f5..1f7d8b64 100644 --- a/views/restaurant.handlebars +++ b/views/restaurant.handlebars @@ -16,6 +16,11 @@

    {{restaurant.description}}

    DashBoard + {{#if isFavorited }} +
    + {{else}} +
    + {{/if}}

    diff --git a/views/restaurants.handlebars b/views/restaurants.handlebars index 4e1df7a2..ab0280cd 100644 --- a/views/restaurants.handlebars +++ b/views/restaurants.handlebars @@ -34,8 +34,12 @@

    {{this.categoryName}}

    {{this.description}}

    -
    -
    + {{#if this.isFavorited }} +
    + {{else}} +
    + {{/if}} From e6fb1f9136c81d29efb950947cd6b05b10d739da Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Sat, 11 Dec 2021 23:02:44 +0800 Subject: [PATCH 100/101] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9Elike/Ulike?= =?UTF-8?q?=E9=A4=90=E5=BB=B3=E5=8A=9F=E8=83=BD(=E7=84=A1=E6=B3=95?= =?UTF-8?q?=E9=80=9A=E9=81=8E=E6=B8=AC=E8=A9=A6=E6=AA=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/passport.js | 3 ++- controllers/restController.js | 14 ++++++----- controllers/userController.js | 18 ++++++++++++++ migrations/20211210053940-create-like.js | 30 ++++++++++++++++++++++++ models/like.js | 24 +++++++++++++++++++ models/restaurant.js | 5 ++++ models/user.js | 5 ++++ routes/index.js | 3 +++ views/restaurant.handlebars | 5 ++++ views/restaurants.handlebars | 19 ++++++++++----- 10 files changed, 113 insertions(+), 13 deletions(-) create mode 100644 migrations/20211210053940-create-like.js create mode 100644 models/like.js diff --git a/config/passport.js b/config/passport.js index a98d9bdc..0974e42a 100644 --- a/config/passport.js +++ b/config/passport.js @@ -30,7 +30,8 @@ passport.serializeUser((user, cb) => { passport.deserializeUser((id, cb) => { User.findByPk(id,{ include: [ - { model: Restaurant, as: 'FavoritedRestaurants' } + { model: Restaurant, as: 'FavoritedRestaurants' }, + { model: Restaurant, as: 'LikedRestaurants' } ] }).then(user => { user = user.toJSON() // 此處與影片示範不同 diff --git a/controllers/restController.js b/controllers/restController.js index 35299481..96072101 100644 --- a/controllers/restController.js +++ b/controllers/restController.js @@ -36,7 +36,8 @@ const restController = { ...r.dataValues, description: r.dataValues.description.substring(0, 50), categoryName: r.dataValues.Category.name, - isFavorited: req.user.FavoritedRestaurants.map(d => d.id).includes(r.id) + isFavorited: req.user.FavoritedRestaurants.map(d => d.id).includes(r.id), + isLiked: req.user.LikedRestaurants.map(d => d.id).includes(r.id) })) Category.findAll({ raw: true, @@ -59,18 +60,19 @@ const restController = { include: [ Category, { model: User, as: 'FavoritedUsers' }, + { model: User, as: 'LikedUsers' }, { model: Comment, include: [User] } ] }).then(restaurant =>{ - const isFavorited = restaurant.FavoritedUsers.map(d => d.id).includes(req.user.id); + const isFavorited = restaurant.FavoritedUsers.map(d => d.id).includes(req.user.id) + const isLiked = restaurant.LikedUsers.map(d => d.id).includes(req.user.id) return restaurant.increment({viewCounts: 1}) .then(() =>res.render('restaurant', { restaurant: restaurant.toJSON(), - isFavorited + isFavorited, + isLiked })) - } - - ) + }) }, getFeeds: (req, res) => { return Promise.all([ diff --git a/controllers/userController.js b/controllers/userController.js index 3732fb3e..754b976b 100644 --- a/controllers/userController.js +++ b/controllers/userController.js @@ -2,10 +2,12 @@ const imgur = require('imgur-node-api') const IMGUR_CLIENT_ID = process.env.IMGUR_CLIENT_ID const bcrypt = require('bcryptjs') const db = require('../models') +const helper = require('../_helpers') const User = db.User const Comment = db.Comment const Restaurant = db.Restaurant const Favorite = db.Favorite +const Like = db.Like const userController = { signUpPage: (req, res) => { @@ -132,6 +134,22 @@ const userController = { return res.redirect('back') }) }) + }, + addLike: (req, res) => { + return Like.create({ + UserId: helper.getUser(req).id, + RestaurantId: req.params.restaurantId + }) + .then(() => res.redirect('back')) + }, + removeLike: (req, res) => { + return Like.destroy({ + where: { + UserId: helper.getUser(req).id, + RestaurantId: req.params.restaurantId + } + }) + .then(() => res.redirect('back')) } } diff --git a/migrations/20211210053940-create-like.js b/migrations/20211210053940-create-like.js new file mode 100644 index 00000000..ad2df697 --- /dev/null +++ b/migrations/20211210053940-create-like.js @@ -0,0 +1,30 @@ +'use strict'; +module.exports = { + up: async (queryInterface, Sequelize) => { + await queryInterface.createTable('Likes', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + UserId: { + type: Sequelize.INTEGER + }, + RestaurantId: { + type: Sequelize.INTEGER + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: async (queryInterface, Sequelize) => { + await queryInterface.dropTable('Likes'); + } +}; \ No newline at end of file diff --git a/models/like.js b/models/like.js new file mode 100644 index 00000000..b45c4dde --- /dev/null +++ b/models/like.js @@ -0,0 +1,24 @@ +'use strict'; +const { + Model +} = require('sequelize'); +module.exports = (sequelize, DataTypes) => { + class Like extends Model { + /** + * Helper method for defining associations. + * This method is not a part of Sequelize lifecycle. + * The `models/index` file will call this method automatically. + */ + static associate(models) { + // define association here + } + }; + Like.init({ + UserId: DataTypes.INTEGER, + RestaurantId: DataTypes.INTEGER + }, { + sequelize, + modelName: 'Like', + }); + return Like; +}; \ No newline at end of file diff --git a/models/restaurant.js b/models/restaurant.js index 2a0df9fe..0ff4d1e9 100644 --- a/models/restaurant.js +++ b/models/restaurant.js @@ -17,6 +17,11 @@ module.exports = (sequelize, DataTypes) => { foreignKey: 'RestaurantId', as: 'FavoritedUsers' }) + Restaurant.belongsToMany(models.User, { + through: models.Like, + foreignKey: 'RestaurantId', + as: 'LikedUsers' + }) } }; Restaurant.init({ diff --git a/models/user.js b/models/user.js index 44d9f0d3..6a299f21 100644 --- a/models/user.js +++ b/models/user.js @@ -16,6 +16,11 @@ module.exports = (sequelize, DataTypes) => { foreignKey: 'UserId', as: 'FavoritedRestaurants' }) + User.belongsToMany(models.Restaurant, { + through: models.Like, + foreignKey: 'UserId', + as: 'LikedRestaurants' + }) } }; User.init({ diff --git a/routes/index.js b/routes/index.js index 808f37ca..37961a72 100644 --- a/routes/index.js +++ b/routes/index.js @@ -66,4 +66,7 @@ module.exports = (app, passport) => { //新增、移除我的最愛 app.post('/favorite/:restaurantId', authenticated, userController.addFavorite) app.delete('/favorite/:restaurantId', authenticated, userController.removeFavorite) + //Like / Unlike + app.post('/like/:restaurantId', authenticated, userController.addLike) + app.delete('/like/:restaurantId', authenticated, userController.removeLike) } diff --git a/views/restaurant.handlebars b/views/restaurant.handlebars index 1f7d8b64..d60fc5f0 100644 --- a/views/restaurant.handlebars +++ b/views/restaurant.handlebars @@ -21,6 +21,11 @@ {{else}}
    {{/if}} + {{#if isLiked }} +
    + {{else}} +
    + {{/if}}
    diff --git a/views/restaurants.handlebars b/views/restaurants.handlebars index ab0280cd..d5f44e55 100644 --- a/views/restaurants.handlebars +++ b/views/restaurants.handlebars @@ -34,12 +34,19 @@

    {{this.categoryName}}

    {{this.description}}

    - {{#if this.isFavorited }} -
    - {{else}} -
    - {{/if}} +
    + {{#if this.isFavorited }} +
    + {{else}} +
    + {{/if}} + {{#if this.isLiked }} +
    + {{else}} +
    + {{/if}} +
    From 540bf981e045443491cc16c57996d8806a8619bb Mon Sep 17 00:00:00 2001 From: HUANG-SIH-MAN Date: Mon, 13 Dec 2021 10:39:07 +0800 Subject: [PATCH 101/101] =?UTF-8?q?fix:=E4=BF=AE=E6=94=B9R04=E6=B8=AC?= =?UTF-8?q?=E8=A9=A6=E6=AA=94=E6=A8=A1=E6=93=AC=E8=B3=87=E6=96=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/R04.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/R04.test.js b/tests/R04.test.js index d736b2f3..fecfb969 100644 --- a/tests/R04.test.js +++ b/tests/R04.test.js @@ -10,8 +10,8 @@ const { createModelMock, createControllerProxy, mockRequest, mockResponse } = re // 建立模擬的 Like 資料 let mockLikeData = [ { - userId: 1, - restaurantId: 2, + UserId: 1, + RestaurantId: 2, }, ]