From cc5000e4915b709b0500fd798b280ebc4728e393 Mon Sep 17 00:00:00 2001 From: Ikechukwu Eze Date: Fri, 6 Sep 2019 16:28:14 +0100 Subject: [PATCH] v1.0 Deploy to production (#55) * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * feature -creates Industries, Mentors and Mentees Table * --no-amend * user router created Co-authored-by: rui * User Auth By Social Media * --no-amend * --no-amend * --no-amend * Added Db configuration and connection changes * --no-amend * --no-amend * --no-amend * Start adding passport local strategy Co-authored-by: Damola Adewunmi Co-authored-by: Ikechukwu Eze * Rename files and fix router to pass tests * ft/create-Mentoring_types-Pivot-Tables -created Mentoring_types, Mentees_choices Mentor_chioces Table -implemented many to many relationship between Mentor Mentee and Mentorying_types * --no-amend * local database connected * Deleted user-router file * --no-amend * --no-amend * --no-amend * Deleted UserAuth file * Deleted mentor test * --no-amend * refactored mentor file to use response helper * Created response helper * Added Create User profile endpoint * Commented out the as keyword from mentor and mentee choices * --no-amend * Added editUserProfile feature * Add bcrypt and add signup endpoint * --no-amend * added tests * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * refactored updateuserProfile * ft/seed-users-table added demo-user username password first_name last_name password and email * --no-amend * --no-amend * wrote some tests for update profile endpoint * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * --no-amend * added mentor controllers * Add OS specific exclusions Based on https://www.gitignore.io/api/linux,macos,windows * Added test for mentorRoute * commented out mentor test file * removed console.log * delete mentor test file * refactored code * Add login functionality and work on social auth * fixed some bugs on mentors and users endpoint * no-amend * Fix signup and login endpoints Co-authored-by: Nmeregini Vincent * Add signup validator * Replace bcrypt with bcryptjs * Remove extra console.log * Remove console;log * fixed getUsers endpoint * turned sequelize scripts to use locally installed executables * Tested getallUsers endpoint * viewUserProfile fixed. bug * Test for viewUserProfile passed * Add comment to mentors controller * Add initial implementation of Github strategy Co-authored-by: Nmeregini Vincent * Changed status codes * made changes as requested * damola changes * GetAllMentors debugged and tested * Add logout endpoint * no_amend * makeUserMentor feature debugged and fixed, tests implemented and passing * deleted comment as requested * All tests passed. Made changes as requested by Vincent * damola changes * Added condition to test * Complete github signup/login * Remove unused logout endpoint * Cleanup code * mentee routes written * Endpoints tested on Insomnia. Working as expected * Added standard tests for mentee endpoints * ft/mentoryinTypes-techName creates techJob table and seeds mentoryingType, techJob table * added niyon logo to mail * Made changes as requested by Rui * Made changes requested by Rui * getallJobs written and tested * Attach token to response when signing up * getMentoringTypes written * Refactored mentoringTypes * Add test * add autocomplete and corresponding tests * removed sum function in index * Remove bio requirement * removed test for unecessary sum function * ft/socialMedia -created social media Table -seeded social media Table -created endpoint to add a user's social media handle * skipped autocomplete test as it takes so much time * Fix bug on update profile endpoint * ft/socialMedia -created social media Table -seeded social media Table -created endpoint to add a user's social media handle * update user password endpoint * tests pass with new account * add more waiting time to image upload test * no-amend * skipped image upload test * update with development * wip * returns unique locations * removed babel-jest and resolved requested changes on the PR * Find or create location endpoint written * refined get user by username data * Made changes to test files * changed expected test result * no_amend * Made the changes as requested * no-amend * Changed validation on location model * Removed auth protection from locatiom route * modified the data that gets returned when fetching all users * Added some more endpoints * uncommented line * Refactored user profile update * made small changes * Made changes as requested by Rui * Fixed validation error on Location * Add Mentee and Mentor to getUserByUsername * Add Mentee and Mentor to getAllUsers * Change token expiration to 14 days --- .circleci/config.yml | 57 +- .coveralls.yml | 2 + .eslintrc.js | 1 - .gitignore | 43 + .sequelizerc | 8 + .vscode/launch.json | 6 +- .vscode/settings.json | 1 + README.md | 2 +- __test__/assests/contact.png | Bin 0 -> 52530 bytes __test__/autocomplete.test.js | 27 + __test__/country.test.js | 33 + __test__/{db.test.js => db.js} | 2 +- __test__/index.test.js | 33 - __test__/jobs.test.js | 13 + __test__/location.test.js | 25 + __test__/mentee.test.js | 166 ++ __test__/mentor.test.js | 113 +- __test__/mentorTypes.test.js | 14 + __test__/users.test.js | 494 ++++ api/controllers/autocomplete.js | 31 + api/controllers/jobs.js | 15 + api/controllers/location.js | 47 + api/controllers/mentee.js | 86 + api/controllers/mentor.js | 83 + api/controllers/mentoringTypes.js | 15 + api/controllers/user.js | 334 +++ api/helpers/jwt.js | 41 + api/helpers/mail.js | 64 + api/helpers/response.js | 15 + api/helpers/users.js | 14 + api/index.js | 19 +- api/mentors/mentor.model.js | 0 api/mentors/mentor.router.js | 11 - api/middleware/authStrategies.js | 122 + api/middleware/cloudinaryImage.js | 24 + api/routes/autocomplete.js | 6 + api/routes/countryRoute.js | 7 + api/routes/jobsRoute.js | 6 + api/routes/locationRoute.js | 11 + api/routes/menteeRoute.js | 29 + api/routes/mentorRoute.js | 29 + api/routes/mentoringTypesRoute.js | 6 + api/routes/userRoute.js | 99 + api/validator/userValidator.js | 107 + config.json | 12 + config/cloudinary.js | 25 + config/secret.js | 25 + conn/index.js | 15 - database/config/config.js | 20 + .../20190820062631-create-locations.js | 32 + .../20190820122327-create-industries.js | 28 + .../20190820211522-create-tech-jobs.js | 36 + .../migrations/20190820212313-create-users.js | 87 + .../20190821123251-create-mentors.js | 48 + .../20190821124406-create-mentees.js | 48 + .../20190822101845-create-mentoring-types.js | 28 + .../20190822115618-create-mentors-chioces.js | 42 + .../20190822122628-create-mentees-chioces.js | 42 + .../20190903084750-create-social-medias.js | 47 + database/models/index.js | 51 + database/models/industries.js | 25 + database/models/locations.js | 35 + database/models/mentees.js | 67 + database/models/mentees_chioces.js | 45 + database/models/mentoring_types.js | 35 + database/models/mentors.js | 67 + database/models/mentors_chioces.js | 45 + database/models/social_medias.js | 36 + database/models/tech_jobs.js | 39 + database/models/users.js | 144 ++ .../seeders/20190827100507-demo-location.js | 27 + database/seeders/20190827181816-demo-user.js | 51 + .../seeders/20190828200447-demo-industry.js | 20 + .../seeders/20190828202308-demo-mentors.js | 22 + .../20190902133818-demo-mentoringType.js | 35 + .../seeders/20190902134855-demo-techJobs.js | 125 + .../20190903092929-demo-socialMedias.js | 24 + index.js | 15 +- package-lock.json | 2132 ++++++++++++----- package.json | 60 +- report.20190826.082443.18640.0.001.json | 442 ++++ server.js | 28 +- 82 files changed, 5699 insertions(+), 667 deletions(-) create mode 100644 .coveralls.yml create mode 100644 .sequelizerc create mode 100644 __test__/assests/contact.png create mode 100644 __test__/autocomplete.test.js create mode 100644 __test__/country.test.js rename __test__/{db.test.js => db.js} (91%) delete mode 100644 __test__/index.test.js create mode 100644 __test__/jobs.test.js create mode 100644 __test__/location.test.js create mode 100644 __test__/mentee.test.js create mode 100644 __test__/mentorTypes.test.js create mode 100644 __test__/users.test.js create mode 100644 api/controllers/autocomplete.js create mode 100644 api/controllers/jobs.js create mode 100644 api/controllers/location.js create mode 100644 api/controllers/mentee.js create mode 100644 api/controllers/mentor.js create mode 100644 api/controllers/mentoringTypes.js create mode 100644 api/controllers/user.js create mode 100644 api/helpers/jwt.js create mode 100644 api/helpers/mail.js create mode 100644 api/helpers/response.js create mode 100644 api/helpers/users.js delete mode 100644 api/mentors/mentor.model.js delete mode 100644 api/mentors/mentor.router.js create mode 100644 api/middleware/authStrategies.js create mode 100644 api/middleware/cloudinaryImage.js create mode 100644 api/routes/autocomplete.js create mode 100644 api/routes/countryRoute.js create mode 100644 api/routes/jobsRoute.js create mode 100644 api/routes/locationRoute.js create mode 100644 api/routes/menteeRoute.js create mode 100644 api/routes/mentorRoute.js create mode 100644 api/routes/mentoringTypesRoute.js create mode 100644 api/routes/userRoute.js create mode 100644 api/validator/userValidator.js create mode 100644 config.json create mode 100644 config/cloudinary.js create mode 100644 config/secret.js delete mode 100644 conn/index.js create mode 100644 database/config/config.js create mode 100644 database/migrations/20190820062631-create-locations.js create mode 100644 database/migrations/20190820122327-create-industries.js create mode 100644 database/migrations/20190820211522-create-tech-jobs.js create mode 100644 database/migrations/20190820212313-create-users.js create mode 100644 database/migrations/20190821123251-create-mentors.js create mode 100644 database/migrations/20190821124406-create-mentees.js create mode 100644 database/migrations/20190822101845-create-mentoring-types.js create mode 100644 database/migrations/20190822115618-create-mentors-chioces.js create mode 100644 database/migrations/20190822122628-create-mentees-chioces.js create mode 100644 database/migrations/20190903084750-create-social-medias.js create mode 100644 database/models/index.js create mode 100644 database/models/industries.js create mode 100644 database/models/locations.js create mode 100644 database/models/mentees.js create mode 100644 database/models/mentees_chioces.js create mode 100644 database/models/mentoring_types.js create mode 100644 database/models/mentors.js create mode 100644 database/models/mentors_chioces.js create mode 100644 database/models/social_medias.js create mode 100644 database/models/tech_jobs.js create mode 100644 database/models/users.js create mode 100644 database/seeders/20190827100507-demo-location.js create mode 100644 database/seeders/20190827181816-demo-user.js create mode 100644 database/seeders/20190828200447-demo-industry.js create mode 100644 database/seeders/20190828202308-demo-mentors.js create mode 100644 database/seeders/20190902133818-demo-mentoringType.js create mode 100644 database/seeders/20190902134855-demo-techJobs.js create mode 100644 database/seeders/20190903092929-demo-socialMedias.js create mode 100644 report.20190826.082443.18640.0.001.json diff --git a/.circleci/config.yml b/.circleci/config.yml index da5dd0d..a2af15f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,28 +5,74 @@ version: 2 jobs: build: + working_directory: ~/repo docker: # specify the version you desire here - image: circleci/node:10.16.0 - + environment: + PGHOST: localhost + PGUSER: postgres + NODE_ENV: test + DIALECT: postgres + DATABASE_URL: "postgres://postgres:postgres@localhost:5432/population_m_s_test" + + - image: circleci/postgres:11 + environment: + POSTGRES_USER: postgres + POSTGRES_DB: population_m_s_test + DIALECT: postgres + POSTGRES_PASSWORD: postgres # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images # documented at https://circleci.com/docs/2.0/circleci-images/ # - image: circleci/mongo:3.4.4 - working_directory: ~/repo + steps: - checkout - # Download and cache dependencies + # # Download and cache dependencies - restore_cache: keys: - v1-dependencies-{{ checksum "package.json" }} # fallback to using the latest cache if no exact match is found - v1-dependencies- - - run: yarn install + - run: + npm install + + - run: + name: Waiting for PostgreSQL to start + command: | + for i in `seq 1 10`; + do + nc -z localhost 5432 && echo Success && exit 0 + echo -n . + sleep 2 + done + echo Failed waiting for Postgres && exit 1 + + # - run: + # name: INSTALL PG CLIENT + # command: sudo apt install -y postgresql-client || true + - run: sudo apt-get update + - run: sudo apt install -y postgresql-client || true + # - run: createdb population-m-s-test + - run: + name: Set up DB + command: | + psql -h localhost -p 5432 -c 'drop database if exists population_m_s_test;' -U postgres + psql -h localhost -p 5432 -c 'create database population_m_s_test;' -U postgres + psql -h localhost -p 5432 -c "CREATE USER postgresql WITH PASSWORD 'postgres';" -U postgres + npx sequelize db:migrate --url "postgres://postgres:postgres@localhost:5432/population_m_s_test" + npx sequelize db:seed:undo:all --url "postgres://postgres:postgres@localhost:5432/population_m_s_test" + npx sequelize db:seed:all --url "postgres://postgres:postgres@localhost:5432/population_m_s_test" + # - run: + # name: "Run Jest and Collect Coverage Reports" + # command: jest --collectCoverage=true + # - store_artifacts: + # path: coverage - save_cache: paths: @@ -34,4 +80,5 @@ jobs: key: v1-dependencies-{{ checksum "package.json" }} # run tests! - - run: yarn test + # - run: npm run testcircleci + - run: npm run test-ci diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..15ac2f7 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1,2 @@ +service_name: circle-ci +repo_token: a6qP3UeAT9QnLIDNtZkEjQuAjTz607lHP \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 0a34485..bad24cc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,6 +1,5 @@ module.exports = { env: { - browser: true, commonjs: true, es6: true, node: true, diff --git a/.gitignore b/.gitignore index f49e348..104161f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,42 @@ pids *.seed *.pid.lock +# Linux +*~ +.fuse_hidden* +.directory +.Trash-* +.nfs* + +# macOS +.DS_Store +.AppleDouble +.LSOverride +Icon +._* +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Windows +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db +*.stackdump +[Dd]esktop.ini +$RECYCLE.BIN/ +*.lnk + # Directory for instrumented libs generated by jscoverage/JSCover lib-cov @@ -60,3 +96,10 @@ typings/ # next.js build output .next # .vscode/launch.json + +# Local Database +# database/ +test.js + +# intellij config files +.idea diff --git a/.sequelizerc b/.sequelizerc new file mode 100644 index 0000000..d799e37 --- /dev/null +++ b/.sequelizerc @@ -0,0 +1,8 @@ +const path = require('path') + +module.exports = { + config: path.resolve('./database/config', 'config.js'), + 'models-path': path.resolve('./database/models'), + 'seeders-path': path.resolve('./database/seeders'), + 'migrations-path': path.resolve('./database/migrations'), +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 144bdc3..aa344f4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,13 +1,11 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { "type": "node", "request": "launch", - "name": "Launch Program", + "name": "Debug", "program": "${workspaceFolder}/index.js" }, { diff --git a/.vscode/settings.json b/.vscode/settings.json index ad92582..a76fb15 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { "editor.formatOnSave": true } + diff --git a/README.md b/README.md index 6f4d425..adfce72 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Coverage Status](https://coveralls.io/repos/github/labseu2-niyon/backend/badge.svg?branch=master)](https://coveralls.io/github/labseu2-niyon/backend?branch=master) +[![Coverage Status](https://coveralls.io/repos/github/labseu2-niyon/backend/badge.svg?branch=development)](https://coveralls.io/github/labseu2-niyon/backend?branch=development) [![CircleCI](https://circleci.com/gh/labseu2-niyon/backend.svg?style=svg)](https://circleci.com/gh/labseu2-niyon/backend) 🚫 Note: All lines that start with 🚫 are instructions and should be deleted before this is posted to your portfolio. This is intended to be a guideline. Feel free to add your own flare to it. diff --git a/__test__/assests/contact.png b/__test__/assests/contact.png new file mode 100644 index 0000000000000000000000000000000000000000..a915f39ebe7f6ab6d8134071a7c43aeef754b6e2 GIT binary patch literal 52530 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 HHq zwJn~oILoeN)x>w!j&(%1_8&EVn-5~snFh*-(gz#s{M=dnOJ*m$9S6 ziIzjfsswx4UcTy{6^?<1MKspATyteSWy-EZTS=``&+Dnix1g5p4F~6s9ys>i!8U#z zt?f7ejSP=@sa!~K&K@(1PvzLDcto!HF@}0ug { + it('should return an array of possible location', async done => { + try { + const res = await request(server).get('/api/autocomplete/enugu'); + expect(res.body.data.length).toBeGreaterThan(0); + expect(res.status).toBe(200); + done(); + } catch (err) { + done(`failed: ${JSON.stringify(err)}`); + } + }); + it('should return an empty array for unknown location', async done => { + try { + const res = await request(server).get( + '/api/autocomplete/xyrgvfggyeye633d' + ); + expect(res.body.data).not.toBeUndefined(); + expect(res.status).toBe(200); + done(); + } catch (err) { + done(`failed: ${JSON.stringify(err)}`); + } + }); +}); diff --git a/__test__/country.test.js b/__test__/country.test.js new file mode 100644 index 0000000..2eaf8b9 --- /dev/null +++ b/__test__/country.test.js @@ -0,0 +1,33 @@ +const request = require('supertest'); +const server = require('../server'); + +describe('GET /api/countries/countries', () => { + it('should return a 201 after getting all countries', () => { + return request(server) + .get('/api/countries/countries') + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data).toHaveLength(2); + }); + }); +}); + +describe('GET /api/countries/:country/cities', () => { + it('should return a 200 if city exists', () => { + return request(server) + .get('/api/countries/Nigeria/cities') + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data).toHaveLength(2); + }); + }); + + it('should return a 200 if city dont exists', () => { + return request(server) + .get('/api/countries/canada/cities') + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data).toBe('No cities saved in the country'); + }); + }); +}); diff --git a/__test__/db.test.js b/__test__/db.js similarity index 91% rename from __test__/db.test.js rename to __test__/db.js index 8a6c4b3..31f136c 100644 --- a/__test__/db.test.js +++ b/__test__/db.js @@ -1,4 +1,4 @@ -const NiyonDB = require('../conn'); +const NiyonDB = require('../database/models'); afterAll(() => { NiyonDB.close(); diff --git a/__test__/index.test.js b/__test__/index.test.js deleted file mode 100644 index 1b7fc68..0000000 --- a/__test__/index.test.js +++ /dev/null @@ -1,33 +0,0 @@ -const { sum, serverVar } = require('../index'); - -afterAll(async () => { - serverVar.close(); -}); - -test('should return sum of two numbers', () => { - expect(sum(3, 5)).toBe(8); -}); - -test('should return sum of three numbers', () => { - expect(sum(3, 4, 5)).toBe(12); -}); - -test('should return sum of spread array of numbers', () => { - expect(sum(...[1, 2, 3, 4, 5, 6, 7, 8, 9, 10])).toBe(55); -}); - -test('should return 0 when only zeroes are passed in', () => { - expect(sum(...[0, 0, 0, 0, 0, 0])).toBe(0); -}); - -test('should throw when passed non-number arguments', () => { - expect(() => { - sum(2, '4'); - }).toThrow('Contains invalid number'); -}); - -test('should throw when passed non-number arguments in a spread array', () => { - expect(() => { - sum(...[1, 2, '8', 4, 5, 6]); - }).toThrow('Contains invalid number'); -}); diff --git a/__test__/jobs.test.js b/__test__/jobs.test.js new file mode 100644 index 0000000..06b9e0f --- /dev/null +++ b/__test__/jobs.test.js @@ -0,0 +1,13 @@ +const request = require('supertest'); +const server = require('../server'); + +describe('Get /jobs/all', () => { + it('should return a 200 code', async () => { + return request(server) + .get('/api/jobs/all') + .then(res => { + expect(res.status).toBe(200); + expect(res.type).toEqual('application/json'); + }); + }); +}); diff --git a/__test__/location.test.js b/__test__/location.test.js new file mode 100644 index 0000000..a4491d5 --- /dev/null +++ b/__test__/location.test.js @@ -0,0 +1,25 @@ +const request = require('supertest'); +const server = require('../server'); + +describe('POST /api/location', () => { + it('should return a 400 if country name is not provided', () => { + return request(server) + .post('/api/location/getLocation') + .send({}) + .then(res => { + expect(res.status).toBe(400); + expect(res.body.message.cityName[0]).toBe( + 'The cityName field is required.' + ); + }); + }); + it('should return a 201 if location was created', () => { + return request(server) + .post('/api/location/getLocation') + .send({ cityName: 'kaduna', countryName: 'Nigeria' }) + .then(res => { + expect(res.status).toBe(201); + expect(res.body.data).toBe(3); + }); + }); +}); diff --git a/__test__/mentee.test.js b/__test__/mentee.test.js new file mode 100644 index 0000000..13e2300 --- /dev/null +++ b/__test__/mentee.test.js @@ -0,0 +1,166 @@ +const request = require('supertest'); +const server = require('../server'); +const jwt = require('../api/helpers/jwt'); + +let serve; +// let agent; + +beforeEach(done => { + serve = server.listen(4000, err => { + if (err) return done(err); + + // agent = request.agent(serve); // since the application is already listening, it should use the allocated port + return done(); + }); +}); + +afterEach(done => { + return serve && serve.close(done); +}); + +describe('Get /mentee/:username/mentees', () => { + it('should return a 200 code', async () => { + const user = { + id: 1, + username: 'john' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/mentee/john/mentees') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(200); + expect(res.type).toEqual('application/json'); + }); + }); + + it('should return 401 if no token is provided', () => { + return request(server) + .get('/api/mentee/john/mentees') + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); + + it('should return a 404 code user does not exist', async () => { + const user = { + id: 5, + username: 'damola' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/mentee/damola/mentees') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(404); + expect(res.body.message).toBe('User not found'); + }); + }); +}); + +describe('POST /mentee/:username/mentee', () => { + it('should return a 201 code', async () => { + const user = { + id: 2, + username: 'john1' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .post('/api/mentee/john1/mentee') + .send({ locationId: 2, industryId: 1 }) + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(201); + expect(res.type).toEqual('application/json'); + }); + }); + it('should return 401 if no token is provided', () => { + return request(server) + .post('/api/mentee/john1/mentee') + .send({ locationId: 2, industryId: 1 }) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); + it('should return a 401 code if the wrong token is sent', async () => { + const user = { + id: 5, + username: 'damola' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .post('/api/mentee/john/mentee') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Error user access'); + }); + }); +}); + +describe('GET /:username', () => { + it('should return 401 if no token is provided', () => { + return request(server) + .get('/api/mentee/john') + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); + + it('should return a 404 code user does not exist', async () => { + const user = { + id: 5, + username: 'damola' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/mentee/damola') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(404); + expect(res.body.message).toBe('User not found'); + }); + }); + it('should return a 200 if user is a mentee', async () => { + const user = { + id: 2, + username: 'john1' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/mentee/john1') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data.mentee).toBe(true); + }); + }); + it('should return 200 and user not a mentee', async () => { + const user = { + id: 3, + username: 'john2' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/mentee/john2') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data).toBe('user is not a mentee'); + }); + }); +}); + +describe('POST /api/mentee/choice', () => { + it('should return 500 if no choice', () => { + return request(server) + .post('/api/mentee/choice') + .send({ mentorTypeId: 10, menteeId: 10 }) + .then(res => { + expect(res.status).toBe(500); + }); + }); +}); diff --git a/__test__/mentor.test.js b/__test__/mentor.test.js index 6130b44..741f497 100644 --- a/__test__/mentor.test.js +++ b/__test__/mentor.test.js @@ -1,20 +1,107 @@ const request = require('supertest'); const server = require('../server'); +const jwt = require('../api/helpers/jwt'); -const app = request(server); +describe('Get /mentor/:username/mentors', () => { + it('should return a 200 code', async () => { + const user = { + id: 1, + username: 'john' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/mentor/john/mentors') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(200); + expect(res.type).toEqual('application/json'); + expect(res.body.data).toHaveLength(1); + }); + }); + + it('should return 401 if no token is provided', () => { + return request(server) + .get('/api/mentor/john/mentors') + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); -describe('Server', () => { - it('[GET] /api/mentors', done => { - return app - .get('/api/mentors') - .expect(200) - .expect('Content-Type', /json/) - .then(res => { - expect(res.body).toBeTruthy(); - done(); - }) - .catch(error => { - done(error); + it('should return a 404 code user does not exist', async () => { + const user = { + id: 5, + username: 'damola' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/mentor/damola/mentors') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(404); + expect(res.body.message).toBe('User not found'); + }); + }); +}); + +describe('POST /mentor/:username/mentor', () => { + it('should return a 201 code', async () => { + const user = { + id: 2, + username: 'john1' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .post('/api/mentor/john1/mentor') + .send({ locationId: 2, industryId: 1 }) + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(201); + expect(res.type).toEqual('application/json'); + expect(res.body.data.IndustryId).toBe(1); + }); + }); + it('should return 401 if no token is provided', () => { + return request(server) + .post('/api/mentor/john1/mentor') + .send({ locationId: 2, industryId: 1 }) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); + it('should return a 401 code if the wrong token is sent', async () => { + const user = { + id: 5, + username: 'damola' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .post('/api/mentor/john/mentor') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Error user access'); + }); + }); +}); + +describe('POST /api/mentor/choice', () => { + it('should return 500 if there are no choices', () => { + return request(server) + .post('/api/mentor/choice') + .send({ mentorTypeId: 20, mentorId: 15 }) + .then(res => { + expect(res.status).toBe(500); + }); + }); + it('should return a 201 if mentor choice was added', () => { + return request(server) + .post('/api/mentor/choice') + .send({ mentorTypeId: 1, mentorId: 1 }) + .then(res => { + expect(res.status).toBe(201); + expect(res.body.data.mentor_id).toBe(1); }); }); }); diff --git a/__test__/mentorTypes.test.js b/__test__/mentorTypes.test.js new file mode 100644 index 0000000..551b6bd --- /dev/null +++ b/__test__/mentorTypes.test.js @@ -0,0 +1,14 @@ +const request = require('supertest'); +const server = require('../server'); + +describe('Get /types/all', () => { + it('should return a 200 code', async () => { + return request(server) + .get('/api/types/all') + .then(res => { + expect(res.status).toBe(200); + expect(res.type).toEqual('application/json'); + expect(res.body.data).toHaveLength(4); + }); + }); +}); diff --git a/__test__/users.test.js b/__test__/users.test.js new file mode 100644 index 0000000..ee39565 --- /dev/null +++ b/__test__/users.test.js @@ -0,0 +1,494 @@ +const request = require('supertest'); +const path = require('path'); +const passport = require('passport'); +const server = require('../server'); +const jwt = require('../api/helpers/jwt'); +const mail = require('../api/helpers/mail'); +const cloudinary = require('../api/middleware/cloudinaryImage'); +const authMiddleware = require('../api/middleware/authStrategies'); + +describe('PATCH /:username/image/upload', () => { + it('should return 401 if no token is provided', () => { + return request(server) + .patch('/api/user/:vincent/image/upload') + .send({}) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); + it('should return 401 if token is invalid', () => { + return request(server) + .patch('/api/user/:vincent/image/upload') + .set({ token: 'gdgfhhrbgegq2ehnfnsnjthrtn' }) + .send() + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Error token type'); + }); + }); + it("should return 404 if user doesn't exists", async () => { + const user = { + id: 1, + username: 'john' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .patch('/api/user/:cristos/image/upload') + .set({ token: jwtToken }) + .send() + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Error user access'); + }); + }); + it('should return 200 for succesful upload', async () => { + const user = { + id: 1, + username: 'john' + }; + jest.spyOn(cloudinary, 'uploadImage').mockResolvedValue({ success: true }); + jest.setTimeout(10000); + const jwtToken = await jwt.generateToken(user); + return request(server) + .patch('/api/user/john/image/upload') + .set({ token: jwtToken }) + .set('Content-Type', 'multipart/form-data') + .attach('image', path.join(__dirname, 'assests/contact.png')) + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data).toContain(1); + }); + }); +}); + +describe('USER PASSWORD RESET', () => { + it('should return 400 if email is not valid', () => { + return request(server) + .post('/api/user/resetpassword') + .send({ email: 'cristos' }) + .then(res => { + expect(res.status).toBe(400); + expect(res.body.message).toBe('Input a valid email'); + }); + }); + it('should return 404 if email is not found', () => { + return request(server) + .post('/api/user/resetpassword') + .send({ email: 'cristos@gmail.com' }) + .then(res => { + expect(res.status).toBe(404); + expect(res.body.message).toBe('User not found'); + }); + }); + it('should send an email', () => { + jest.spyOn(mail, 'passwordResetMail').mockResolvedValue({ success: true }); + return request(server) + .post('/api/user/resetpassword') + .send({ email: 'nmereginivincent@gmail.com' }) + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data).toBe('Email sent to nmereginivincent@gmail.com'); + }); + }); + it('should return a 400 if password type is not correct', () => { + return request(server) + .patch('/api/user/newpassword') + .send({ password: '123' }) + .then(res => { + expect(res.status).toBe(400); + expect(res.body.message).toBe('Password must be at least 5 characters'); + }); + }); + it('should return 401 with invalid token', () => { + return request(server) + .patch('/api/user/newpassword?token="yregfdbdhdghghhfdhdh"') + .send({ password: '1234567' }) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Invalid token to reset password'); + }); + }); + it('should return a 400 if token is expired', () => { + return request(server) + .patch('/api/user/newpassword?token=niyon') + .send({ password: '1234567' }) + .then(res => { + expect(res.status).toBe(400); + expect(res.body.message).toBe('Password reset have expired'); + }); + }); + it('should return a 200 for successful password reset', () => { + return request(server) + .patch('/api/user/newpassword?token=niyonapp') + .send({ password: '1234567' }) + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data).toBe('Password reset was succesful'); + }); + }); +}); + +describe('GET /users', () => { + it('should return a 200 code', async () => { + const user = { + id: 1, + username: 'john' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/user/john/users') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data).toHaveLength(3); + }); + }); + + it('should return 401 if no token is provided', () => { + return request(server) + .get('/api/user/john/users') + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); +}); + +describe('GET user profile information', () => { + it('should return a 200 code', async () => { + const user = { + id: 1, + username: 'john' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/user/john/profile') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(200); + }); + }); + + it('should return a 401 code if token does not match user', async () => { + const user = { + id: 1, + username: 'john' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/user/damola/profile') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Error user access'); + }); + }); + + it('should return a 404 code user does not exist', async () => { + const user = { + id: 5, + username: 'damola' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .get('/api/user/damola/profile') + .set({ token: jwtToken }) + .then(res => { + expect(res.status).toBe(404); + expect(res.body.message).toBe('User not found'); + }); + }); + + it('should return 401 if no token is provided', () => { + return request(server) + .get('/api/user/john/profile') + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); +}); + +describe('POST user update social media info', () => { + it('should return 401 if no token is provided', () => { + return request(server) + .post('/api/user/vincent/socialmedia') + .send({}) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); + it('should return 401 if token is invalid', () => { + return request(server) + .post('/api/user/vincent/socialmedia') + .set({ token: 'gdgfhhrbgegq2ehnfnsnjthrtn' }) + .send() + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Error token type'); + }); + }); + it("should return 404 if user doesn't exists", async () => { + const user = { + id: 1, + username: 'john123' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .post('/api/user/john123/socialmedia') + .set({ token: jwtToken }) + .send({}) + .then(res => { + expect(res.status).toBe(404); + expect(res.body.message).toBe('User not found'); + }); + }); + it('should return 400 if body is empty', async () => { + const user = { + id: 1, + username: 'john' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .post('/api/user/john/socialmedia') + .set({ token: jwtToken }) + .send({}) + .then(res => { + expect(res.status).toBe(400); + expect(res.body.message).toBe('Empty body not allowed'); + }); + }); + it('should return a 201 when social media is updated', async () => { + const user = { + id: 1, + username: 'john' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .post('/api/user/john/socialmedia') + .set({ token: jwtToken }) + .send({ facebook: 'userfacebooking' }) + .then(res => { + expect(res.status).toBe(201); + }); + }); +}); + +describe('POST Create User', () => { + it('should return 400 if username is not provided', () => { + const user = { + email: 'gmail@gmail.com', + password: '123456789' + }; + return request(server) + .post('/api/user/signup') + .send(user) + .then(res => { + expect(res.status).toBe(400); + expect(res.body.message.username[0]).toBe( + 'The username field is required.' + ); + }); + }); + it('should return a 400 if user already exists', () => { + const user = { + username: 'John', + email: 'gmail@gmail.com', + password: '123456789' + }; + + return request(server) + .post('/api/user/signup') + .send(user) + .then(res => { + expect(res.status).toBe(400); + expect(res.body.message).toBe( + 'User already registered with username or email provided' + ); + }); + }); + it('should return a 201 when user is created successfully', async () => { + const user = { + username: 'Johnson', + email: 'gmail@gmail.com', + password: '123456789' + }; + return request(server) + .post('/api/user/signup') + .send(user) + .then(res => { + expect(res.status).toBe(201); + expect(res.body.data.user.email).toBe(user.email); + }); + }); +}); + +describe('POST Login User', () => { + it('should return 400 if email type is not valid', () => { + const user = { + email: 'email' + }; + return request(server) + .post('/api/user/login') + .send(user) + .then(res => { + expect(res.status).toBe(400); + expect(res.body.message).toBe('Input a valid email'); + }); + }); + it('should return 404 if user does not exists', () => { + const user = { + email: 'email@gmail.com' + }; + return request(server) + .post('/api/user/login') + .send(user) + .then(res => { + expect(res.status).toBe(404); + expect(res.body.message).toBe('User not found'); + }); + }); + it('should return 401 if credentials are not valid', () => { + const user = { + email: 'nmereginivincent@gmail.com', + password: '123456789' + }; + return request(server) + .post('/api/user/login') + .send(user) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Invalid credentials'); + }); + }); + it('should return 200 when details are correct', () => { + const user = { + email: 'nmereginivincent@gmail.com', + password: 'password' + }; + return request(server) + .post('/api/user/login') + .send(user) + .then(res => { + expect(res.status).toBe(200); + expect(res.body.data.message).toBe( + `${user.email} successfully logged in.` + ); + }); + }); +}); + +describe('GET /auth/github', () => { + it('should return 302', () => { + jest + .spyOn(authMiddleware, 'githubStrategy') + .mockResolvedValue({ success: true }); + return request(server) + .get('/api/user/auth/github/') + .then(res => { + expect(res.status).toBe(302); + }); + }); + it('should return 302', () => { + jest + .spyOn(authMiddleware, 'githubStrategy') + .mockResolvedValue({ success: true }); + jest.spyOn(passport, 'authenticate').mockResolvedValue({ success: true }); + return request(server) + .get('/api/user/auth/github/callback') + .then(res => { + expect(res.status).toBe(302); + }); + }); +}); + +describe('PATCH /api/user/:username/password', () => { + it('should return 401 if no token is provided', () => { + return request(server) + .patch('/api/user/:vincent/password') + .send({}) + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Token is required'); + }); + }); + it('should return 401 if token is invalid', () => { + return request(server) + .patch('/api/user/:vincent/password') + .set({ token: 'gdgfhhrbgegq2ehnfnsnjthrtn' }) + .send() + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Error token type'); + }); + }); + it("should return 404 if user doesn't exists", async () => { + const user = { + id: 1, + username: 'john' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .patch('/api/user/:vincent/password') + .set({ token: jwtToken }) + .send() + .then(res => { + expect(res.status).toBe(401); + expect(res.body.message).toBe('Error user access'); + }); + }); + it("should return 404 if user doesn't exists", async () => { + const user = { + id: 1, + username: 'vincent' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .patch('/api/user/vincent/password') + .set({ token: jwtToken }) + .send() + .then(res => { + expect(res.status).toBe(404); + expect(res.body.message).toBe('User not found'); + }); + }); + it("should return 403 if password don't match old password", async () => { + const user = { + id: 1, + username: 'john' + }; + const body = { + password: '12345678', + newPassword: 'password' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .patch('/api/user/john/password') + .set({ token: jwtToken }) + .send(body) + .then(res => { + expect(res.status).toBe(403); + expect(res.body.message).toBe('Password did not match'); + }); + }); + it('should return 200 if password is updated', async () => { + const user = { + id: 1, + username: 'john' + }; + const body = { + password: 'password', + newPassword: 'password' + }; + const jwtToken = await jwt.generateToken(user); + return request(server) + .patch('/api/user/john/password') + .set({ token: jwtToken }) + .send(body) + .then(res => { + expect(res.status).toBe(200); + }); + }); +}); diff --git a/api/controllers/autocomplete.js b/api/controllers/autocomplete.js new file mode 100644 index 0000000..2b94ba7 --- /dev/null +++ b/api/controllers/autocomplete.js @@ -0,0 +1,31 @@ +require('dotenv').config(); +const fetch = require('node-fetch'); +const uuid = require('uuid'); +const response = require('../helpers/response'); + +module.exports = { + async autoComplete(req, res) { + const { place } = req.params; + try { + const request = await fetch( + `https://maps.googleapis.com/maps/api/place/autocomplete/json?input=${place} + &key=${process.env.PLACE_API_KEY}&sessiontoken=${uuid()}&geometry` + ); + const result = await request.json(); + const locations = result.predictions.map(p => p.description); + // returns the city and country from each location + const reformed = locations + .map(v => v.split`,`) + .map(a => + a + .slice(-2) + .join(',') + .trim() + ); + // new Set(reformed) removes duplicate locations + response.success(res, 200, [...new Set(reformed)]); + } catch (error) { + response.error(res, 500, `Couldn't get possible locations`); + } + } +}; diff --git a/api/controllers/jobs.js b/api/controllers/jobs.js new file mode 100644 index 0000000..649669c --- /dev/null +++ b/api/controllers/jobs.js @@ -0,0 +1,15 @@ +const models = require('../../database/models'); +const response = require('../helpers/response'); + +module.exports = { + async getAllJobs(req, res) { + try { + const jobs = await models.Tech_jobs.findAll({ + attributes: ['id', 'tech_name'] + }); + return response.success(res, 200, jobs); + } catch (error) { + return response.error(res, 500, error.message); + } + } +}; diff --git a/api/controllers/location.js b/api/controllers/location.js new file mode 100644 index 0000000..874b0d5 --- /dev/null +++ b/api/controllers/location.js @@ -0,0 +1,47 @@ +const models = require('../../database/models'); +const response = require('../helpers/response'); + +module.exports = { + async getCountries(req, res, next) { + try { + const countries = await models.Locations.findAll({ + attributes: ['country_name'], + returning: true + }); + return response.success(res, 200, countries); + } catch (error) { + return next({ message: error.message }); + } + }, + // currently not in use + async getCitiesByCountries(req, res, next) { + try { + const { country } = req.params; + const cities = await models.Locations.findAll({ + attributes: ['city_name'], + where: { country_name: country }, + returning: true + }); + if (!cities.length) { + return response.success(res, 200, 'No cities saved in the country'); + } + return response.success(res, 200, cities); + } catch (error) { + return next({ message: error.message }); + } + }, + + async findOrCreateLocation(req, res, next) { + try { + const { cityName, countryName } = req.body; + const locations = await models.Locations.findOrCreate({ + where: { country_name: countryName, city_name: cityName }, + attributes: ['id'] + }); + const locationId = locations[0].dataValues.id; + return response.success(res, 201, locationId); + } catch (error) { + return next({ message: error.message }); + } + } +}; diff --git a/api/controllers/mentee.js b/api/controllers/mentee.js new file mode 100644 index 0000000..4160c0d --- /dev/null +++ b/api/controllers/mentee.js @@ -0,0 +1,86 @@ +/* eslint-disable no-dupe-keys */ +const models = require('../../database/models'); +const response = require('../helpers/response'); + +module.exports = { + async getAllMentees(req, res) { + try { + const mentees = await models.Mentees.findAll({ + attributes: ['user_id', 'industry_id', 'location_id'], + include: [ + { + model: models.Industries, + attributes: ['industry_name'], + as: 'industry' + }, + { + model: models.Users, + attributes: [ + 'first_name', + 'last_name', + 'biography', + 'profile_picture' + ], + as: 'user', + required: true, + include: [ + { + model: models.Locations, + attributes: ['country_name', 'city_name'], + as: 'location' + } + ] + } + ] + }); + return response.success(res, 200, mentees); + } catch (error) { + return response.error(res, 500, error.message); + } + }, + + async makeUserMentee(req, res) { + try { + const { locationId, industryId } = req.body; + const userId = req.user.id; + const mentee = await models.Mentees.create({ + user_id: userId, + location_id: locationId, + industry_id: industryId + }); + return response.success(res, 201, mentee); + } catch (error) { + return response.error(res, 500, error.message); + } + }, + + async checkIfUserIsMentee(req, res) { + try { + const userId = req.user.id; + const mentee = await models.Mentees.findOne({ + where: { user_id: userId }, + attributes: ['id', 'location_id', 'industry_id'] + }); + if (mentee) { + const newMentee = { mentee: true }; + return response.success(res, 200, newMentee); + } + return response.success(res, 200, 'user is not a mentee'); + } catch (error) { + return response.error(res, 500, error.message); + } + }, + + async addMenteeChoice(req, res) { + try { + const { mentorTypeId, menteeId } = req.body; + const menteeChoice = await models.Mentees_choices.create({ + mentoring_type_id: mentorTypeId, + mentee_id: menteeId + }); + return response.success(res, 201, menteeChoice); + } catch (error) { + return response.error(res, 500, error.message); + } + } +}; diff --git a/api/controllers/mentor.js b/api/controllers/mentor.js new file mode 100644 index 0000000..483d4ee --- /dev/null +++ b/api/controllers/mentor.js @@ -0,0 +1,83 @@ +/* eslint-disable no-dupe-keys */ +const models = require('../../database/models'); +const response = require('../helpers/response'); + +module.exports = { + async getAllMentors(req, res) { + try { + const mentors = await models.Mentors.findAll({ + attributes: ['user_id', 'industry_id', 'location_id'], + include: [ + { + model: models.Industries, + attributes: ['industry_name'], + as: 'industry' + }, + { + model: models.Users, + attributes: [ + 'first_name', + 'last_name', + 'biography', + 'profile_picture' + ], + as: 'user', + required: true, + include: [ + { + model: models.Locations, + attributes: ['country_name', 'city_name'], + as: 'location' + } + ] + } + ] + }); + return response.success(res, 200, mentors); + } catch (error) { + return response.error(res, 500, error.message); + } + }, + + async makeUserMentor(req, res) { + try { + const { locationId, industryId } = req.body; + const userId = req.user.id; + const mentor = await models.Mentors.create({ + user_id: userId, + location_id: locationId, + industry_id: industryId + }); + return response.success(res, 201, mentor); + } catch (error) { + return response.error(res, 500, error.message); + } + }, + + async checkIfUserIsMentor(req, res) { + try { + const userId = req.user.id; + await models.Mentors.findOne({ + where: { user_id: userId }, + attributes: ['id', 'location_id', 'industry_id'] + }); + const newMentor = { mentor: true }; + return response.success(res, 200, newMentor); + } catch (error) { + return response.error(res, 500, error.message); + } + }, + + async addMentorChoice(req, res) { + try { + const { mentorTypeId, mentorId } = req.body; + const mentorChoice = await models.Mentors_choices.create({ + mentoring_type_id: mentorTypeId, + mentor_id: mentorId + }); + return response.success(res, 201, mentorChoice); + } catch (error) { + return response.error(res, 500, error.message); + } + } +}; diff --git a/api/controllers/mentoringTypes.js b/api/controllers/mentoringTypes.js new file mode 100644 index 0000000..9fc3454 --- /dev/null +++ b/api/controllers/mentoringTypes.js @@ -0,0 +1,15 @@ +const models = require('../../database/models'); +const response = require('../helpers/response'); + +module.exports = { + async getAllTypes(req, res) { + try { + const types = await models.Mentoring_types.findAll({ + attributes: ['id', 'mentor_type_name'] + }); + return response.success(res, 200, types); + } catch (error) { + return response.error(res, 500, error.message); + } + } +}; diff --git a/api/controllers/user.js b/api/controllers/user.js new file mode 100644 index 0000000..0b3c8fa --- /dev/null +++ b/api/controllers/user.js @@ -0,0 +1,334 @@ +const crypto = require('crypto'); +const bcrypt = require('bcryptjs'); +const models = require('../../database/models'); +const response = require('../helpers/response'); +const mail = require('../helpers/mail'); +const secret = require('../../config/secret'); +const jwt = require('../helpers/jwt'); + +module.exports = { + async getUserByUsername(req, res) { + try { + const { username } = req.params; + const user = await models.Users.findOne({ + where: { username }, + attributes: [ + 'id', + 'first_name', + 'last_name', + 'username', + 'email', + 'biography', + 'profile_picture' + ], + include: [ + { + model: models.Locations, + attributes: ['id', 'city_name', 'country_name'], + as: 'location' + }, + { + model: models.Mentees, + attributes: ['id'], + as: 'Mentee', + include: [ + { + model: models.Industries, + attributes: ['industry_name'], + as: 'industry' + } + ] + }, + { + model: models.Mentors, + attributes: ['id'], + as: 'Mentor', + include: [ + { + model: models.Industries, + attributes: ['industry_name'], + as: 'industry' + } + ] + }, + { + model: models.Tech_jobs, + attributes: ['tech_name'], + as: 'job', + include: [ + { + model: models.Industries, + attributes: ['industry_name'], + as: 'industry' + } + ] + } + ] + }); + return response.success(res, 200, user); + } catch (error) { + return response.error(res, 500, error.message); + } + }, + + async getAllUsers(req, res, next) { + try { + const users = await models.Users.findAll({ + attributes: [ + 'id', + 'first_name', + 'last_name', + 'username', + 'email', + 'biography', + 'profile_picture' + ], + include: [ + { + model: models.Locations, + attributes: ['id', 'city_name', 'country_name'], + as: 'location' + }, + { + model: models.Mentees, + attributes: ['id'], + as: 'Mentee', + include: [ + { + model: models.Industries, + attributes: ['industry_name'], + as: 'industry' + } + ] + }, + { + model: models.Mentors, + attributes: ['id'], + as: 'Mentor', + include: [ + { + model: models.Industries, + attributes: ['industry_name'], + as: 'industry' + } + ] + }, + { + model: models.Tech_jobs, + attributes: ['tech_name'], + as: 'job' + } + ] + }); + if (users) return response.success(res, 200, users); + return response.error(res, 404, 'Could not fetch all users'); + } catch (error) { + return next({ message: error.message }); + } + }, + + async updateUserPassword(req, res, next) { + try { + const { username } = req.params; + const { password, newPassword } = req.body; + const hash = await bcrypt.hash(newPassword, 14); + if (!bcrypt.compareSync(password, req.user.password)) { + return response.error(res, 403, 'Password did not match'); + } + const updatePassword = await models.Users.update( + { + password: hash + }, + { where: { username }, returning: true } + ); + return response.success(res, 200, updatePassword); + } catch (error) { + return next({ + message: error.message + }); + } + }, + + async updateUserProfile(req, res, next) { + try { + const { username } = req.params; + const { firstName, lastName, bio, locationId, jobId } = req.body; + + // const locations = await models.Locations.findOrCreate({ + // where: { country_name: countryName, city_name: cityName }, + // attributes: ['id'] + // }); + // const locationId = locations[0].dataValues.id; + // if (!locationId) { + // return response.error(res, 404, 'Location not found'); + // } + const updateUser = await models.Users.update( + { + first_name: firstName, + last_name: lastName, + biography: bio, + location_id: locationId, + job_id: jobId + }, + { where: { username }, returning: true } + ); + return response.success(res, 200, updateUser); + } catch (error) { + return next({ message: 'Error updating profile' }); + } + }, + + async createUser(req, res) { + try { + const createUser = { + ...req.body, + email: req.body.email.toLowerCase(), + username: req.body.username.toLowerCase() + }; + const user = await models.Users.create(createUser); + if (user) { + const newUser = { + password: user.password, + username: user.username, + email: user.email, + id: user.id + }; + + const token = await jwt.generateToken(newUser); + return response.success(res, 201, { user: newUser, token }); + } + return response.error(res, 400, 'Could not create Profile'); + } catch (error) { + return response.error(res, 500, error.message); + } + }, + + async loginUser(req, res, next) { + const { email, password } = req.body; + + try { + const user = await models.Users.findOne({ + where: { email }, + attributes: ['password', 'email', 'username', 'id'] + }); + if ( + Object.keys(user).length && + bcrypt.compareSync(password, user.dataValues.password) + ) { + const token = await jwt.generateToken(user.dataValues); + return response.success(res, 200, { + message: `${email} successfully logged in.`, + token + }); + } + return response.error(res, 401, 'Invalid credentials'); + } catch (error) { + return next({ message: 'Error logging in user' }); + } + }, + + async socialAuthlogin(req, res, next) { + const { user } = req; + + try { + const token = await jwt.generateToken(user.dataValues); + + return response.success(res, 200, { + message: `${user.dataValues.email} successfully logged in.`, + token + }); + } catch (error) { + return next({ message: `${error.message}` }); + } + }, + + async uploadUserImage(req, res, next) { + const { params, file } = req; + try { + const user = await models.Users.update( + { profile_picture: file.secure_url, public_id: file.public_id }, + { where: { username: params.username }, returning: true } + ); + return response.success(res, 200, user); + } catch (error) { + return next({ message: 'Error updating image' }); + } + }, + + async sendPasswordMail(req, res, next) { + const token = await crypto.randomBytes(20).toString('hex'); + const expiringDate = Date.now() + 360000; + try { + const sendMail = await mail.passwordResetMail( + secret.frontEndUrl, + token, + req.userEmail.email, + req.userEmail.username + ); + if (!sendMail) { + return response.error(res, 400, 'Error sending mail try again'); + } + await models.Users.update( + { + reset_password_token: token, + reset_password_expires: expiringDate + }, + { where: { email: req.userEmail.email } } + ); + return response.success(res, 200, `Email sent to ${req.userEmail.email}`); + } catch (error) { + return next({ message: 'Error sending mail tryagain' }); + } + }, + + async resetPassword(req, res, next) { + const { token } = req.query; + try { + const user = await models.Users.findOne({ + where: { reset_password_token: token }, + attributes: ['reset_password_expires', 'id'] + }); + if (!user) { + return response.error(res, 401, 'Invalid token to reset password'); + } + const savedDate = user.dataValues.reset_password_expires; + const date = Date.now() - savedDate; + if (date > 0) { + return response.error(res, 400, 'Password reset have expired'); + } + const hash = await bcrypt.hash(req.body.password, 14); + const newUserPassword = await models.Users.update( + { + password: hash, + // reset_password_expires: '', + reset_password_token: '' + }, + { + where: { id: user.dataValues.id } + } + ); + if (!newUserPassword) { + return response.error(res, 404, 'User not found'); + } + return response.success(res, 200, 'Password reset was succesful'); + } catch (error) { + return next({ message: error.message }); + } + }, + + async addSocialMediaAccount(req, res, next) { + try { + const { body } = req; + if (!Object.keys(body).length) { + return response.error(res, 400, 'Empty body not allowed'); + } + const socialMedia = await models.Social_medias.create({ + ...body, + user_id: req.user.id + }); + return response.success(res, 201, socialMedia); + } catch (error) { + return next({ message: 'Error posting users social media handle' }); + } + } +}; diff --git a/api/helpers/jwt.js b/api/helpers/jwt.js new file mode 100644 index 0000000..67f80f2 --- /dev/null +++ b/api/helpers/jwt.js @@ -0,0 +1,41 @@ +const jwt = require('jsonwebtoken'); +const secret = require('../../config/secret'); +const response = require('./response'); + +module.exports = { + async generateToken(user) { + const payload = { + subject: user.id, + username: user.username + }; + + const options = { + expiresIn: '14d' + }; + + const token = await jwt.sign(payload, secret.jwtSecret, options); + return token; + }, + + async authUser(req, res, next) { + const { token } = req.headers; + if (!token) { + return response.error(res, 401, 'Token is required'); + } + try { + const decode = await jwt.verify(token, secret.jwtSecret); + req.decode = decode; + } catch (error) { + return response.error(res, 401, 'Error token type'); + } + try { + const { username } = req.params; + if (username !== req.decode.username) { + return response.error(res, 401, 'Error user access'); + } + return next(); + } catch (error) { + return next({ message: 'Error validating User' }); + } + } +}; diff --git a/api/helpers/mail.js b/api/helpers/mail.js new file mode 100644 index 0000000..7bc4a47 --- /dev/null +++ b/api/helpers/mail.js @@ -0,0 +1,64 @@ +const nodemailer = require('nodemailer'); +const Mailgen = require('mailgen'); +const secret = require('../../config/secret'); + +const logo = + 'https://res.cloudinary.com/niyon/image/upload/v1567491149/Group_2_3_pezgbf.png'; + +async function passwordResetMail(url, token, email, username) { + const mailGenerator = new Mailgen({ + theme: 'default', + product: { + name: 'Niyon', + link: `${url}`, + logo + } + }); + const mail = { + body: { + name: username, + intro: + 'You have received this email because a password reset request for your account was received.', + action: { + instructions: 'Click the button below to reset your password:', + button: { + color: '#DC4D2F', + text: 'Reset your password', + link: `${url}?token=${token}` + } + }, + outro: + 'If you did not request a password reset, no further action is required on your part.' + } + }; + const emailBody = mailGenerator.generate(mail); + + const emailText = mailGenerator.generatePlaintext(mail); + const transporter = nodemailer.createTransport({ + host: 'smtp.gmail.com', + port: 465, + secure: true, + // requireTLS: true + auth: { + user: secret.USER_MAIL, + pass: secret.PASSWORD_MAIL + } + }); + + const mailOption = { + from: 'niyonlabs@gmail.com', + to: email, + subject: 'Password Reset', + html: emailBody, + text: emailText + }; + + try { + const passwordMail = await transporter.sendMail(mailOption); + return passwordMail; + } catch (error) { + return error.message; + } +} + +module.exports = { passwordResetMail }; diff --git a/api/helpers/response.js b/api/helpers/response.js new file mode 100644 index 0000000..542c813 --- /dev/null +++ b/api/helpers/response.js @@ -0,0 +1,15 @@ +module.exports = { + success(res, status, data) { + return res.status(status).json({ + status, + data + }); + }, + + error(res, status, message) { + return res.status(status).json({ + status, + message + }); + } +}; diff --git a/api/helpers/users.js b/api/helpers/users.js new file mode 100644 index 0000000..95ff963 --- /dev/null +++ b/api/helpers/users.js @@ -0,0 +1,14 @@ +const models = require('../../database/models'); + +module.exports = { + async findUserByUsername(username) { + try { + const user = await models.Users.findOne({ + where: { username } + }); + return user; + } catch (error) { + return error.message; + } + } +}; diff --git a/api/index.js b/api/index.js index e94cd0f..6c6e2f5 100644 --- a/api/index.js +++ b/api/index.js @@ -1,7 +1,22 @@ const router = require('express').Router(); // Export routes from here -const mentorRouter = require('./mentors/mentor.router'); -router.use('/mentors', mentorRouter); +const userRouter = require('./routes/userRoute'); +const locationRouter = require('./routes/locationRoute'); +const mentorRouter = require('./routes/mentorRoute'); +const countryRouter = require('./routes/countryRoute'); +const autoCompleteRouter = require('./routes/autocomplete'); +const jobsRouter = require('./routes/jobsRoute'); +const mentorTypes = require('./routes/mentoringTypesRoute'); +const menteeRouter = require('./routes/menteeRoute'); + +router.use('/user', userRouter); +router.use('/mentor', mentorRouter); +router.use('/mentee', menteeRouter); +router.use('/jobs', jobsRouter); +router.use('/types', mentorTypes); +router.use('/countries', countryRouter); +router.use('/autocomplete', autoCompleteRouter); +router.use('/location', locationRouter); module.exports = router; diff --git a/api/mentors/mentor.model.js b/api/mentors/mentor.model.js deleted file mode 100644 index e69de29..0000000 diff --git a/api/mentors/mentor.router.js b/api/mentors/mentor.router.js deleted file mode 100644 index b842636..0000000 --- a/api/mentors/mentor.router.js +++ /dev/null @@ -1,11 +0,0 @@ -const router = require('express').Router(); - -router.get('/', (_, res) => { - res.status(200).json({ - name: 'Captain Mentor', - company: 'Amentors', - role: 'First Mentor' - }); -}); - -module.exports = router; diff --git a/api/middleware/authStrategies.js b/api/middleware/authStrategies.js new file mode 100644 index 0000000..00d7917 --- /dev/null +++ b/api/middleware/authStrategies.js @@ -0,0 +1,122 @@ +const passport = require('passport'); +const FaceBookStrategy = require('passport-facebook').Strategy; +const GitHubStrategy = require('passport-github').Strategy; +const GoogleStrategy = require('passport-google-oauth').Strategy; +const LinkedInStrategy = require('passport-linkedin'); +const TwitterStrategy = require('passport-twitter').Strategy; +const models = require('../../database/models'); +const keys = require('../../config/secret'); + +passport.serializeUser((user, done) => { + done(null, user.id); +}); + +passport.deserializeUser((id, done) => { + models.Users.findByPk(id, (err, user) => { + done(err, user); + }); +}); + +async function callbackStrategy(profile, cb) { + const email = profile.emails[0].value; + + try { + const existingUser = await models.Users.findOne({ where: { email } }); + if (!existingUser) { + const newUser = await models.Users.findOrCreate({ + where: { auth_id: profile.id }, + defaults: { username: profile.username, email, password: ' ' } + }); + if (!newUser) { + return new Error(); + } + return cb(null, newUser); + } + return cb(null, existingUser); + } catch (error) { + return cb(error, null); + } +} + +function githubStrategy() { + return new GitHubStrategy( + { + clientID: keys.GITHUB_CLIENT_ID, + clientSecret: keys.GITHUB_CLIENT_SECRET, + callbackURL: '/api/user/auth/github/callback', + scope: 'user:email' + }, + (accessToken, refreshToken, profile, cb) => { + return callbackStrategy(profile, cb); + } + ); +} + +function facebookStrategy() { + passport.use( + new FaceBookStrategy( + { + clientID: keys.FACEBOOK_APP_ID, + clientSecret: keys.FACEBOOK_APP_SECRET, + callbackURL: '/login/?provider=facebook/redirect', + profileFields: ['id', 'first-name', 'last-name', 'email-address'] + }, + (accessToken, refreshToken, profile, cb) => { + return callbackStrategy(profile, cb); + } + ) + ); +} + +function googleStrategy() { + passport.use( + new GoogleStrategy( + { + clientID: keys.GOOGLE_CLIENT_ID, + clientSecret: keys.GOOGLE_CLIENT_SECRET, + callbackURL: 'auth/google/redirect' + }, + (accessToken, refreshToken, profile, cb) => { + return callbackStrategy(profile, cb); + } + ) + ); +} + +function linkedinStrategy() { + passport.use( + new LinkedInStrategy( + { + consumerKey: keys.LINKEDIN_API_KEY, + consumerSecret: keys.LINKEDIN_SECRET_KEY, + callbackURL: '/login/?provider=linkedIn/redirect' + }, + (accessToken, refreshToken, profile, cb) => { + return callbackStrategy(profile, cb); + } + ) + ); +} + +function twitterStrategy() { + passport.use( + new TwitterStrategy( + { + clientID: keys.TWITTER_CONSUMER_KEY, + clientSecret: keys.TWITTER_CONSUMER_SECRET, + callbackURL: '/login/?provider=twitter/redirect' + }, + (accessToken, refreshToken, profile, cb) => { + return callbackStrategy(profile, cb); + } + ) + ); +} + +module.exports = { + facebookStrategy, + githubStrategy, + googleStrategy, + linkedinStrategy, + twitterStrategy +}; diff --git a/api/middleware/cloudinaryImage.js b/api/middleware/cloudinaryImage.js new file mode 100644 index 0000000..a5ca1ed --- /dev/null +++ b/api/middleware/cloudinaryImage.js @@ -0,0 +1,24 @@ +const cloudinary = require('cloudinary'); +const multer = require('multer'); +const response = require('../helpers/response'); +const storage = require('../../config/cloudinary'); + +module.exports = { + async deleteCloudImage(req, res, next) { + if (req.user.public_id) { + try { + const deleteCloudImage = await cloudinary.uploader.destroy( + req.user.public_id + ); + req.deleteCloudImage = deleteCloudImage; + } catch (error) { + return response.error(error.message); + } + } + return next(); + }, + uploadImage(image) { + const parser = multer({ storage }); + return parser.single(image); + } +}; diff --git a/api/routes/autocomplete.js b/api/routes/autocomplete.js new file mode 100644 index 0000000..6367e1d --- /dev/null +++ b/api/routes/autocomplete.js @@ -0,0 +1,6 @@ +const router = require('express').Router(); +const controller = require('../controllers/autocomplete'); + +router.get('/:place', controller.autoComplete); + +module.exports = router; diff --git a/api/routes/countryRoute.js b/api/routes/countryRoute.js new file mode 100644 index 0000000..dd93ff7 --- /dev/null +++ b/api/routes/countryRoute.js @@ -0,0 +1,7 @@ +const router = require('express').Router(); +const controller = require('../controllers/location'); + +router.get('/countries', controller.getCountries); +router.get('/:country/cities', controller.getCitiesByCountries); + +module.exports = router; diff --git a/api/routes/jobsRoute.js b/api/routes/jobsRoute.js new file mode 100644 index 0000000..e8a2f67 --- /dev/null +++ b/api/routes/jobsRoute.js @@ -0,0 +1,6 @@ +const router = require('express').Router(); +const controller = require('../controllers/jobs'); + +router.get('/all', controller.getAllJobs); + +module.exports = router; diff --git a/api/routes/locationRoute.js b/api/routes/locationRoute.js new file mode 100644 index 0000000..61a0f8f --- /dev/null +++ b/api/routes/locationRoute.js @@ -0,0 +1,11 @@ +const router = require('express').Router(); +const controller = require('../controllers/location'); +const userValidators = require('../validator/userValidator'); + +router.post( + '/getLocation', + userValidators.validateLocationInfo, + controller.findOrCreateLocation +); + +module.exports = router; diff --git a/api/routes/menteeRoute.js b/api/routes/menteeRoute.js new file mode 100644 index 0000000..c92a86f --- /dev/null +++ b/api/routes/menteeRoute.js @@ -0,0 +1,29 @@ +const router = require('express').Router(); +const auth = require('../helpers/jwt'); +const userValidator = require('../validator/userValidator'); +const controller = require('../controllers/mentee'); + +// router.get('/', (req, res) => { +// res.status(200).json('Mentor routes can be seen here'); +// }); +router.get( + '/:username/mentees', + [auth.authUser, userValidator.validateUserExists], + controller.getAllMentees +); + +router.get( + '/:username', + [auth.authUser, userValidator.validateUserExists], + controller.checkIfUserIsMentee +); + +router.post( + '/:username/mentee', + [auth.authUser, userValidator.validateUserExists], + controller.makeUserMentee +); + +router.post('/choice', controller.addMenteeChoice); + +module.exports = router; diff --git a/api/routes/mentorRoute.js b/api/routes/mentorRoute.js new file mode 100644 index 0000000..d8fabd4 --- /dev/null +++ b/api/routes/mentorRoute.js @@ -0,0 +1,29 @@ +const router = require('express').Router(); +const auth = require('../helpers/jwt'); +const userValidator = require('../validator/userValidator'); +const controller = require('../controllers/mentor'); + +// router.get('/', (req, res) => { +// res.status(200).json('Mentor routes can be seen here'); +// }); +router.get( + '/:username/mentors', + [auth.authUser, userValidator.validateUserExists], + controller.getAllMentors +); + +router.get( + '/:username', + [auth.authUser, userValidator.validateUserExists], + controller.checkIfUserIsMentor +); + +router.post( + '/:username/mentor', + [auth.authUser, userValidator.validateUserExists], + controller.makeUserMentor +); + +router.post('/choice', controller.addMentorChoice); + +module.exports = router; diff --git a/api/routes/mentoringTypesRoute.js b/api/routes/mentoringTypesRoute.js new file mode 100644 index 0000000..e198820 --- /dev/null +++ b/api/routes/mentoringTypesRoute.js @@ -0,0 +1,6 @@ +const router = require('express').Router(); +const controller = require('../controllers/mentoringTypes'); + +router.get('/all', controller.getAllTypes); + +module.exports = router; diff --git a/api/routes/userRoute.js b/api/routes/userRoute.js new file mode 100644 index 0000000..aa44a2e --- /dev/null +++ b/api/routes/userRoute.js @@ -0,0 +1,99 @@ +const router = require('express').Router(); +const passport = require('passport'); +const controller = require('../controllers/user'); +const userValidators = require('../validator/userValidator'); +const cloudinary = require('../middleware/cloudinaryImage'); +const authUser = require('../helpers/jwt'); + +router.get( + '/:username/users', + [authUser.authUser, userValidators.validateUserExists], + controller.getAllUsers +); +router.get( + '/:username/profile', + [authUser.authUser, userValidators.validateUserExists], + controller.getUserByUsername +); +router.patch( + '/:username/profile', + [ + authUser.authUser, + userValidators.validateUserExists, + userValidators.validateUserProfileUpdate + ], + controller.updateUserProfile +); + +router.patch( + '/:username/password', + [authUser.authUser, userValidators.validateUserExists], + controller.updateUserPassword +); + +router.patch( + '/:username/image/upload', + [ + authUser.authUser, + userValidators.validateUserExists, + cloudinary.uploadImage('image'), + cloudinary.deleteCloudImage + ], + controller.uploadUserImage +); + +// Auth Routes +router.post( + '/signup', + [userValidators.validateUserSignup], + controller.createUser +); + +router.post('/login', [userValidators.validateUserEmail], controller.loginUser); + +// Github +router.get('/auth/github', passport.authenticate('github', { session: false })); + +router.get( + '/auth/github/callback', + passport.authenticate('github', { + failureMessage: 'Error logging in with github' + }), + + controller.socialAuthlogin +); + +// router.get('/login/?provider=facebook', [ +// passport.authenticate('facebook', { +// scope: ['profile'] +// }) +// ]); + +// router.get( +// '/login/?provider=facebook/redirect', +// passport.authenticate('facebook', { failureRedirect: '/login' }), +// (req, res) => { +// // Successful authentication, redirect home. +// res.redirect('/'); +// } +// ); + +router.post( + '/resetpassword', + [userValidators.validateUserEmail], + controller.sendPasswordMail +); + +router.patch( + '/newpassword', + [userValidators.validatePassword], + controller.resetPassword +); + +router.post( + '/:username/socialmedia', + [authUser.authUser, userValidators.validateUserExists], + controller.addSocialMediaAccount +); + +module.exports = router; diff --git a/api/validator/userValidator.js b/api/validator/userValidator.js new file mode 100644 index 0000000..4530c9b --- /dev/null +++ b/api/validator/userValidator.js @@ -0,0 +1,107 @@ +const Validator = require('validatorjs'); +const Sequelize = require('sequelize'); +const response = require('../helpers/response'); +const userQuery = require('../helpers/users'); +const models = require('../../database/models'); + +module.exports = { + async validateUserExists(req, res, next) { + const { username } = req.params; + try { + const user = await userQuery.findUserByUsername(username); + if (!user) return response.error(res, 404, 'User not found'); + req.user = user; + return next(); + } catch (errors) { + return next({ message: 'Server error try again' }); + } + }, + async validateUserEmail(req, res, next) { + const { email } = req.body; + const validator = new Validator(req.body, { + email: 'required|email' + }); + if (validator.fails()) { + return response.error(res, 400, 'Input a valid email'); + } + try { + const user = await models.Users.findOne({ + where: { email }, + attributes: ['email', 'username', 'id'] + }); + if (!user) { + return response.error(res, 404, 'User not found'); + } + req.userEmail = user; + return next(); + } catch (error) { + return next({ message: 'Server error try again' }); + } + }, + + validatePassword(req, res, next) { + const { body } = req; + const validator = new Validator(body, { + password: 'required|min:5' + }); + if (validator.fails()) { + return response.error(res, 400, 'Password must be at least 5 characters'); + } + return next(); + }, + + validateUserProfileUpdate(req, res, next) { + const validator = new Validator(req.body, { + firstName: 'required|alpha', + lastName: 'required|alpha' + }); + if (validator.fails()) { + return response.error(res, 400, validator.errors.all()); + } + return next(); + }, + + validateLocationInfo(req, res, next) { + const validator = new Validator(req.body, { + countryName: 'required', + cityName: 'required' + }); + if (validator.fails()) { + return response.error(res, 400, validator.errors.all()); + } + return next(); + }, + + async validateUserSignup(req, res, next) { + const validator = new Validator(req.body, { + username: 'required|alpha_num', + password: 'required|min:8', + email: 'required|email' + }); + + if (validator.fails()) { + return response.error(res, 400, validator.errors.all()); + } + try { + const user = await models.Users.findOne({ + where: { + [Sequelize.Op.or]: [ + { email: req.body.email.toLowerCase() }, + { username: req.body.username.toLowerCase() } + ] + }, + attributes: ['id'] + }); + if (!user) { + return next(); + } + return response.error( + res, + 400, + 'User already registered with username or email provided' + ); + } catch (error) { + return next({ message: 'Error validating user signup' }); + } + } +}; diff --git a/config.json b/config.json new file mode 100644 index 0000000..ebbe621 --- /dev/null +++ b/config.json @@ -0,0 +1,12 @@ +{ + "testMatch": ["/tests/unit/*.js"], + + "transform": { + ".*": "/node_modules/babel-jest" + }, + "moduleFileExtensions": ["js"], + "collectCoverageFrom": [ + "src/*.js", + "!src/index.js" + ] +} \ No newline at end of file diff --git a/config/cloudinary.js b/config/cloudinary.js new file mode 100644 index 0000000..34749bd --- /dev/null +++ b/config/cloudinary.js @@ -0,0 +1,25 @@ +const cloudinary = require('cloudinary'); +const cloudinaryStorage = require('multer-storage-cloudinary'); +const secret = require('./secret'); + +cloudinary.config({ + cloud_name: secret.cloudinaryName, + api_key: secret.cloudinaryApiKey, + api_secret: secret.cloudinaryApiSecret +}); + +const err = new Error('image type must be png or jpg'); +const storage = cloudinaryStorage({ + cloudinary, + folder: 'niyon-app', + allowedFormats: ['jpg', 'png'], + transformation: [{ width: 300, height: 300, crop: 'limit' }], + filename(req, file, cb) { + if (file.mimetype === 'image/png' || file.mimetype === 'image/jpg') { + cb(null, true); + } else { + cb(err.message, false); + } + } +}); +module.exports = storage; diff --git a/config/secret.js b/config/secret.js new file mode 100644 index 0000000..5d44efe --- /dev/null +++ b/config/secret.js @@ -0,0 +1,25 @@ +require('dotenv').config(); + +module.exports = { + DEV_DATABASE_URL: process.env.DATABASE_URL, + DATABASE_URL_TEST: process.env.DEV_DATABASE_URL, + DATABASE_URL: process.env.DATABASE_URL, + DIALECT: process.env.DIALECT, + PG_HOST: process.env.PG_HOST, + POSTGRES_DB: process.env.POSTGRES_DB, + POSTGRES_USER: process.env.POSTGRES_USER, + POSTGRES_PASSWORD: process.env.POSTGRES_PASSWORD, + GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID, + GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET, + FACEBOOK_APP_ID: process.env.FACEBOOK_APP_ID, + FACEBOOK_APP_SECRET: process.env.FACEBOOK_APP_SECRET, + LINKEDIN_API_KEY: process.env.LINKEDIN_API_KEY, + LINKEDIN_SECRET_KEY: process.env.LINKEDIN_SECRET_KEY, + cloudinaryName: process.env.CLOUDINARY_NAME, + cloudinaryApiKey: process.env.CLOUDINARY_API_KEY, + cloudinaryApiSecret: process.env.CLOUDINARY_API_SECRET, + jwtSecret: process.env.JWT_SECRET, + frontEndUrl: process.env.FRONT_END_URL, + USER_MAIL: process.env.USER_MAIL, + PASSWORD_MAIL: process.env.PASSWORD_MAIL +}; diff --git a/conn/index.js b/conn/index.js deleted file mode 100644 index 36dfc48..0000000 --- a/conn/index.js +++ /dev/null @@ -1,15 +0,0 @@ -require('dotenv').config(); -const Sequelize = require('sequelize'); - -// env from .env -const development = ` -postgres://${process.env.DB_USER}:${process.env.DB_PASS}@${process.env.DB_HOST}:5432/${process.env.DB_DATABASE}`; - -// env set on heroku/circleCI/AWS => DATABASE_URL -const dbUrl = process.env.DATABASE_URL - ? `${process.env.DATABASE_URL}?ssl=true` - : development; - -const db = new Sequelize(dbUrl); - -module.exports = db; diff --git a/database/config/config.js b/database/config/config.js new file mode 100644 index 0000000..9b75a95 --- /dev/null +++ b/database/config/config.js @@ -0,0 +1,20 @@ +const secret = require('../../config/secret'); + +module.exports = { + development: { + url: secret.DEV_DATABASE_URL, + dialect: 'postgres' + }, + test: { + url: secret.DATABASE_URL_TEST, + dialect: 'postgres' + }, + staging: { + url: secret.DATABASE_URL, + dialect: 'postgres' + }, + production: { + url: secret.DATABASE_URL, + dialect: 'postgres' + } +}; diff --git a/database/migrations/20190820062631-create-locations.js b/database/migrations/20190820062631-create-locations.js new file mode 100644 index 0000000..e92559f --- /dev/null +++ b/database/migrations/20190820062631-create-locations.js @@ -0,0 +1,32 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Locations', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + country_name: { + type: Sequelize.STRING, + allowNull: false + }, + city_name: { + type: Sequelize.STRING, + allowNull: false + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Locations'); + } +}; diff --git a/database/migrations/20190820122327-create-industries.js b/database/migrations/20190820122327-create-industries.js new file mode 100644 index 0000000..83d1db5 --- /dev/null +++ b/database/migrations/20190820122327-create-industries.js @@ -0,0 +1,28 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Industries', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + industry_name: { + type: Sequelize.STRING, + allowNull: false + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Industries'); + } +}; diff --git a/database/migrations/20190820211522-create-tech-jobs.js b/database/migrations/20190820211522-create-tech-jobs.js new file mode 100644 index 0000000..ef9afbc --- /dev/null +++ b/database/migrations/20190820211522-create-tech-jobs.js @@ -0,0 +1,36 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Tech_jobs', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + tech_name: { + type: Sequelize.STRING, + allowNull: false + }, + industry_id: { + type: Sequelize.INTEGER, + references: { + model: 'Industries', + key: 'id', + as: 'industry' + } + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Tech_jobs'); + } +}; diff --git a/database/migrations/20190820212313-create-users.js b/database/migrations/20190820212313-create-users.js new file mode 100644 index 0000000..0289680 --- /dev/null +++ b/database/migrations/20190820212313-create-users.js @@ -0,0 +1,87 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Users', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + auth_id: { + type: Sequelize.STRING, + allowNull: true, + unique: true + }, + first_name: { + type: Sequelize.STRING, + allowNull: true + }, + last_name: { + type: Sequelize.STRING, + allowNull: true + }, + email: { + type: Sequelize.STRING, + allowNull: false, + unique: true + }, + password: { + type: Sequelize.STRING, + allowNull: true + }, + biography: { + type: Sequelize.STRING, + allowNull: true + }, + profile_picture: { + type: Sequelize.STRING, + allowNull: true + }, + public_id: { + type: Sequelize.STRING, + allowNull: true + }, + username: { + type: Sequelize.STRING, + allowNull: false, + unique: true + }, + reset_password_token: { + type: Sequelize.STRING, + allowNull: true + }, + reset_password_expires: { + type: Sequelize.BIGINT, + allowNull: true + }, + location_id: { + type: Sequelize.INTEGER, + references: { + model: 'Locations', + key: 'id', + as: 'location' + } + }, + job_id: { + type: Sequelize.INTEGER, + references: { + model: 'Tech_jobs', + key: 'id', + as: 'job' + } + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Users'); + } +}; diff --git a/database/migrations/20190821123251-create-mentors.js b/database/migrations/20190821123251-create-mentors.js new file mode 100644 index 0000000..a46e352 --- /dev/null +++ b/database/migrations/20190821123251-create-mentors.js @@ -0,0 +1,48 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Mentors', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + user_id: { + type: Sequelize.INTEGER, + references: { + model: 'Users', + key: 'id', + as: 'location' + } + }, + location_id: { + type: Sequelize.INTEGER, + references: { + model: 'Locations', + key: 'id', + as: 'location' + } + }, + industry_id: { + type: Sequelize.INTEGER, + references: { + model: 'Industries', + key: 'id', + as: 'location' + } + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Mentors'); + } +}; diff --git a/database/migrations/20190821124406-create-mentees.js b/database/migrations/20190821124406-create-mentees.js new file mode 100644 index 0000000..10c2157 --- /dev/null +++ b/database/migrations/20190821124406-create-mentees.js @@ -0,0 +1,48 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Mentees', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + user_id: { + type: Sequelize.INTEGER, + references: { + model: 'Users', + key: 'id', + as: 'location' + } + }, + location_id: { + type: Sequelize.INTEGER, + references: { + model: 'Locations', + key: 'id', + as: 'location' + } + }, + industry_id: { + type: Sequelize.INTEGER, + references: { + model: 'Industries', + key: 'id', + as: 'location' + } + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Mentees'); + } +}; diff --git a/database/migrations/20190822101845-create-mentoring-types.js b/database/migrations/20190822101845-create-mentoring-types.js new file mode 100644 index 0000000..a1b150d --- /dev/null +++ b/database/migrations/20190822101845-create-mentoring-types.js @@ -0,0 +1,28 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Mentoring_types', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + mentor_type_name: { + type: Sequelize.STRING, + allowNull: false + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Mentoring_types'); + } +}; diff --git a/database/migrations/20190822115618-create-mentors-chioces.js b/database/migrations/20190822115618-create-mentors-chioces.js new file mode 100644 index 0000000..0abc9a4 --- /dev/null +++ b/database/migrations/20190822115618-create-mentors-chioces.js @@ -0,0 +1,42 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Mentors_choices', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + mentoring_type_id: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'Mentoring_types', + key: 'id' + // as: 'location' + } + }, + mentor_id: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'Mentors', + key: 'id' + // as: 'location' + } + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Mentors_choices'); + } +}; diff --git a/database/migrations/20190822122628-create-mentees-chioces.js b/database/migrations/20190822122628-create-mentees-chioces.js new file mode 100644 index 0000000..de64c00 --- /dev/null +++ b/database/migrations/20190822122628-create-mentees-chioces.js @@ -0,0 +1,42 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Mentees_choices', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + mentoring_type_id: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'Mentoring_types', + key: 'id' + // as: 'type' + } + }, + mentee_id: { + type: Sequelize.INTEGER, + allowNull: false, + references: { + model: 'Mentees', + key: 'id' + // as: 'location' + } + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Mentees_choices'); + } +}; diff --git a/database/migrations/20190903084750-create-social-medias.js b/database/migrations/20190903084750-create-social-medias.js new file mode 100644 index 0000000..b80d0e8 --- /dev/null +++ b/database/migrations/20190903084750-create-social-medias.js @@ -0,0 +1,47 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('Social_medias', { + id: { + allowNull: false, + autoIncrement: true, + primaryKey: true, + type: Sequelize.INTEGER + }, + user_id: { + type: Sequelize.INTEGER, + references: { + model: 'Users', + key: 'id', + as: 'user' + } + }, + facebook: { + type: Sequelize.STRING, + allowNull: true, + unique: true + }, + twitter: { + type: Sequelize.STRING, + allowNull: true, + unique: true + }, + linkedin: { + type: Sequelize.STRING, + allowNull: true, + unique: true + }, + created_at: { + allowNull: false, + type: Sequelize.DATE + }, + updated_at: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('Social_medias'); + } +}; diff --git a/database/models/index.js b/database/models/index.js new file mode 100644 index 0000000..1b1efe9 --- /dev/null +++ b/database/models/index.js @@ -0,0 +1,51 @@ +/* eslint-disable import/no-dynamic-require */ +/* eslint-disable prettier/prettier */ +require('dotenv').config(); +const fs = require('fs'); +const path = require('path'); +const Sequelize = require('sequelize'); + +const basename = path.basename(__filename); +const env = process.env.NODE_ENV || 'development'; +const config = require(`${__dirname }/../config/config.js`)[env]; +const db = {}; + +let sequelize; +if (config.use_env_variable) { + sequelize = new Sequelize(process.env[config.use_env_variable]); + } +else { + sequelize = new Sequelize( + config.url, + { + host: 'localhost', + dialect: 'postgres', + define: { + underscored: true, + freezeTableName: true, + }, + } + ); +} + +fs.readdirSync(__dirname) + .filter(file => { + return ( + file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js' + ); + }) + .forEach(file => { + const model = sequelize.import(path.join(__dirname, file)); + db[model.name] = model; + }); + +Object.keys(db).forEach(modelName => { + if (db[modelName].associate) { + db[modelName].associate(db); + } +}); + +db.sequelize = sequelize; +db.Sequelize = Sequelize; + +module.exports = db; diff --git a/database/models/industries.js b/database/models/industries.js new file mode 100644 index 0000000..01cf573 --- /dev/null +++ b/database/models/industries.js @@ -0,0 +1,25 @@ +module.exports = (sequelize, DataTypes) => { + const Industries = sequelize.define( + 'Industries', + { + industry_name: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isAlphanumeric: { + args: true, + msg: 'Please enter your industry name' + } + } + } + }, + {} + ); + Industries.associate = models => { + // associations can be defined here + Industries.hasMany(models.Mentors); + Industries.hasMany(models.Mentees); + Industries.hasMany(models.Tech_jobs); + }; + return Industries; +}; diff --git a/database/models/locations.js b/database/models/locations.js new file mode 100644 index 0000000..90bbabb --- /dev/null +++ b/database/models/locations.js @@ -0,0 +1,35 @@ +module.exports = (sequelize, DataTypes) => { + const Locations = sequelize.define( + 'Locations', + { + country_name: { + type: DataTypes.STRING, + allowNull: false, + validate: { + min: { + args: 2, + msg: 'Country name should be atleast 2 characters long' + } + } + }, + city_name: { + type: DataTypes.STRING, + allowNull: false, + validate: { + min: { + args: 2, + msg: 'City name should be atleast 2 characters long' + } + } + } + }, + {} + ); + Locations.associate = models => { + // associations can be defined here + Locations.hasMany(models.Users); + Locations.hasMany(models.Mentors); + Locations.hasMany(models.Mentees); + }; + return Locations; +}; diff --git a/database/models/mentees.js b/database/models/mentees.js new file mode 100644 index 0000000..dfe3be8 --- /dev/null +++ b/database/models/mentees.js @@ -0,0 +1,67 @@ +module.exports = (sequelize, DataTypes) => { + const Mentees = sequelize.define( + 'Mentees', + { + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter your location' + } + } + }, + location_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter your location' + } + } + }, + industry_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isAlphanumeric: { + args: true, + msg: 'Please enter your industry name' + } + } + } + }, + {} + ); + Mentees.associate = models => { + // associations can be defined here + Mentees.belongsTo(models.Users, { + foreignKey: 'user_id', + as: 'user', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Mentees.belongsTo(models.Locations, { + foreignKey: 'location_id', + as: 'location', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Mentees.belongsTo(models.Industries, { + foreignKey: 'industry_id', + as: 'industry', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Mentees.belongsToMany(models.Mentoring_types, { + through: 'Mentees_choices', + foreignKey: 'mentoring_type_id', + as: 'Mentee_choice', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + }; + return Mentees; +}; diff --git a/database/models/mentees_chioces.js b/database/models/mentees_chioces.js new file mode 100644 index 0000000..4b64213 --- /dev/null +++ b/database/models/mentees_chioces.js @@ -0,0 +1,45 @@ +/* eslint-disable camelcase */ +module.exports = (sequelize, DataTypes) => { + const Mentees_choices = sequelize.define( + 'Mentees_choices', + { + mentoring_type_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter your mentoring type id' + } + } + }, + mentee_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter your mentee id' + } + } + } + }, + {} + ); + Mentees_choices.associate = models => { + // associations can be defined here + Mentees_choices.belongsTo(models.Mentoring_types, { + foreignKey: 'mentoring_type_id', + // as: 'mentee_type_id', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Mentees_choices.belongsTo(models.Mentees, { + foreignKey: 'mentee_id', + // as: 'mentee_id', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + }; + return Mentees_choices; +}; diff --git a/database/models/mentoring_types.js b/database/models/mentoring_types.js new file mode 100644 index 0000000..7b7040e --- /dev/null +++ b/database/models/mentoring_types.js @@ -0,0 +1,35 @@ +/* eslint-disable camelcase */ +module.exports = (sequelize, DataTypes) => { + const Mentoring_types = sequelize.define( + 'Mentoring_types', + { + mentor_type_name: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isAlphanumeric: { + args: true, + msg: 'Please enter mentoring type name' + } + } + } + }, + {} + ); + Mentoring_types.associate = models => { + // associations can be defined here + Mentoring_types.belongsToMany(models.Mentors, { + through: 'Mentors_choices', + foreignKey: 'mentor_id', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Mentoring_types.belongsToMany(models.Mentees, { + through: 'Mentees_choices', + foreignKey: 'mentee_id', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + }; + return Mentoring_types; +}; diff --git a/database/models/mentors.js b/database/models/mentors.js new file mode 100644 index 0000000..3f70046 --- /dev/null +++ b/database/models/mentors.js @@ -0,0 +1,67 @@ +module.exports = (sequelize, DataTypes) => { + const Mentors = sequelize.define( + 'Mentors', + { + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter your location' + } + } + }, + location_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter your location' + } + } + }, + industry_id: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isAlphanumeric: { + args: true, + msg: 'Please enter your industry name' + } + } + } + }, + {} + ); + Mentors.associate = models => { + // associations can be defined here + Mentors.belongsTo(models.Users, { + foreignKey: 'user_id', + as: 'user', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Mentors.belongsTo(models.Locations, { + foreignKey: 'location_id', + as: 'location', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Mentors.belongsTo(models.Industries, { + foreignKey: 'industry_id', + as: 'industry', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Mentors.belongsToMany(models.Mentoring_types, { + through: 'Mentors_choices', + foreignKey: 'mentoring_type_id', + as: 'Mentor_choice', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + }; + return Mentors; +}; diff --git a/database/models/mentors_chioces.js b/database/models/mentors_chioces.js new file mode 100644 index 0000000..f194e4f --- /dev/null +++ b/database/models/mentors_chioces.js @@ -0,0 +1,45 @@ +/* eslint-disable camelcase */ +module.exports = (sequelize, DataTypes) => { + const Mentors_choices = sequelize.define( + 'Mentors_choices', + { + mentoring_type_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter your mentoring type id' + } + } + }, + mentor_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter your mentor id' + } + } + } + }, + {} + ); + Mentors_choices.associate = models => { + // associations can be defined here + Mentors_choices.belongsTo(models.Mentoring_types, { + foreignKey: 'mentoring_type_id', + // as: 'mentoring_type_id', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Mentors_choices.belongsTo(models.Mentors, { + foreignKey: 'mentor_id', + // as: 'mentor_id', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + }; + return Mentors_choices; +}; diff --git a/database/models/social_medias.js b/database/models/social_medias.js new file mode 100644 index 0000000..9e03b4e --- /dev/null +++ b/database/models/social_medias.js @@ -0,0 +1,36 @@ +/* eslint-disable camelcase */ +module.exports = (sequelize, DataTypes) => { + const Social_medias = sequelize.define( + 'Social_medias', + { + user_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter a valid user id' + } + } + }, + facebook: { + type: DataTypes.STRING, + allowNull: true + }, + linkedin: { + type: DataTypes.STRING, + allowNull: true + }, + twitter: { + type: DataTypes.STRING, + allowNull: true + } + }, + {} + ); + Social_medias.associate = models => { + // associations can be defined here + Social_medias.belongsTo(models.Users); + }; + return Social_medias; +}; diff --git a/database/models/tech_jobs.js b/database/models/tech_jobs.js new file mode 100644 index 0000000..5cb4fe8 --- /dev/null +++ b/database/models/tech_jobs.js @@ -0,0 +1,39 @@ +/* eslint-disable camelcase */ +module.exports = (sequelize, DataTypes) => { + const Tech_jobs = sequelize.define( + 'Tech_jobs', + { + tech_name: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isAlpha: { + args: true, + msg: 'Please enter a valid tech_name' + } + } + }, + industry_id: { + type: DataTypes.INTEGER, + allowNull: false, + validate: { + isInt: { + args: true, + msg: 'Please enter industry' + } + } + } + }, + {} + ); + Tech_jobs.associate = models => { + // associations can be defined here + Tech_jobs.belongsTo(models.Industries, { + foriegnKey: 'industry_id', + as: 'industry', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + }; + return Tech_jobs; +}; diff --git a/database/models/users.js b/database/models/users.js new file mode 100644 index 0000000..c3f3982 --- /dev/null +++ b/database/models/users.js @@ -0,0 +1,144 @@ +/* eslint-disable no-underscore-dangle */ +const bcrypt = require('bcryptjs'); + +module.exports = (sequelize, DataTypes) => { + const Users = sequelize.define( + 'Users', + { + first_name: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isAlphanumeric: { + args: true, + msg: 'Please enter your firstname' + } + } + }, + last_name: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isAlphanumeric: { + args: true, + msg: 'Please enter your lastname' + } + } + }, + username: { + type: DataTypes.STRING, + allowNull: false, + validate: { + notNull: { + args: true, + msg: 'Please enter your username' + } + } + }, + email: { + type: DataTypes.STRING, + allowNull: false, + validate: { + isEmail: { + args: true, + msg: 'Please enter a valid email' + } + } + }, + password: { + type: DataTypes.STRING, + allowNull: true + }, + biography: { + type: DataTypes.STRING, + allowNull: true + }, + profile_picture: { + type: DataTypes.STRING, + allowNull: true + }, + public_id: { + type: DataTypes.STRING, + allowNull: true + }, + reset_password_token: { + type: DataTypes.STRING, + allowNull: true + }, + reset_password_expires: { + type: DataTypes.BIGINT, + allowNull: true + }, + location_id: { + type: DataTypes.INTEGER, + allowNull: true, + validate: { + isInt: { + args: true, + msg: 'Please enter your location' + } + } + }, + job_id: { + type: DataTypes.INTEGER, + allowNull: true, + validate: { + isInt: { + args: true, + msg: 'Please enter your job' + } + } + }, + auth_id: { + type: DataTypes.STRING, + allowNull: true, + validate: { + isAlphanumeric: { + args: true, + msg: 'Please enter the user id from social auth' + } + } + } + }, + { + hooks: { + beforeCreate: user => Users.hashPassword(user), + beforeUpdate: user => Users.hashPassword(user) + } + } + ); + Users.associate = models => { + // associations can be defined here + Users.belongsTo(models.Locations, { + foreignKey: 'location_id', + as: 'location', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Users.belongsTo(models.Tech_jobs, { + foreignKey: 'job_id', + as: 'job', + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }); + Users.hasOne(models.Mentors); + Users.hasOne(models.Mentees); + Users.hasMany(models.Social_medias); + }; + Users.hashPassword = async user => { + // console.log(user); + const changedPassword = await user.changed( + 'password', + user.dataValues.password + ); + if ( + changedPassword._previousDataValues.password !== + changedPassword.dataValues.password + ) { + const hash = await bcrypt.hash(user.dataValues.password, 14); + await user.setDataValue('password', hash); + } + return user; + }; + return Users; +}; diff --git a/database/seeders/20190827100507-demo-location.js b/database/seeders/20190827100507-demo-location.js new file mode 100644 index 0000000..e0e3fc3 --- /dev/null +++ b/database/seeders/20190827100507-demo-location.js @@ -0,0 +1,27 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.bulkInsert( + 'Locations', + [ + { + country_name: 'Nigeria', + city_name: 'Lagos', + created_at: new Date(), + updated_at: new Date() + }, + { + country_name: 'Nigeria', + city_name: 'Enugu', + created_at: new Date(), + updated_at: new Date() + } + ], + {} + ); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.bulkDelete('Locations', null, {}); + } +}; diff --git a/database/seeders/20190827181816-demo-user.js b/database/seeders/20190827181816-demo-user.js new file mode 100644 index 0000000..a2c5455 --- /dev/null +++ b/database/seeders/20190827181816-demo-user.js @@ -0,0 +1,51 @@ +/* eslint-disable no-unused-vars */ +const bcrypt = require('bcryptjs'); + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.bulkInsert( + 'Users', + [ + { + first_name: 'John', + last_name: 'Doe', + email: 'nmereginivincent@gmail.com', + password: bcrypt.hashSync('password', 14), + username: 'john', + location_id: 1, + created_at: new Date(), + updated_at: new Date() + }, + { + first_name: 'John', + last_name: 'Doe', + email: 'c001@gmail.com', + password: bcrypt.hashSync('password', 14), + username: 'john1', + reset_password_token: 'niyon', + reset_password_expires: Date.now(), + location_id: 2, + created_at: new Date(), + updated_at: new Date() + }, + { + first_name: 'John', + last_name: 'Doe', + email: 'c0012@gmail.com', + password: bcrypt.hashSync('password', 14), + username: 'john2', + reset_password_token: 'niyonapp', + reset_password_expires: Date.now() + 360000, + location_id: 2, + created_at: new Date(), + updated_at: new Date() + } + ], + {} + ); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.bulkDelete('Users', null, {}); + } +}; diff --git a/database/seeders/20190828200447-demo-industry.js b/database/seeders/20190828200447-demo-industry.js new file mode 100644 index 0000000..f0fdc4b --- /dev/null +++ b/database/seeders/20190828200447-demo-industry.js @@ -0,0 +1,20 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.bulkInsert( + 'Industries', + [ + { + industry_name: 'Technology', + created_at: new Date(), + updated_at: new Date() + } + ], + {} + ); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.bulkDelete('Industries', null, {}); + } +}; diff --git a/database/seeders/20190828202308-demo-mentors.js b/database/seeders/20190828202308-demo-mentors.js new file mode 100644 index 0000000..a54dded --- /dev/null +++ b/database/seeders/20190828202308-demo-mentors.js @@ -0,0 +1,22 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.bulkInsert( + 'Mentors', + [ + { + user_id: 1, + location_id: 1, + industry_id: 1, + created_at: new Date(), + updated_at: new Date() + } + ], + {} + ); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.bulkDelete('Mentors', null, {}); + } +}; diff --git a/database/seeders/20190902133818-demo-mentoringType.js b/database/seeders/20190902133818-demo-mentoringType.js new file mode 100644 index 0000000..c736b7a --- /dev/null +++ b/database/seeders/20190902133818-demo-mentoringType.js @@ -0,0 +1,35 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.bulkInsert( + 'Mentoring_types', + [ + { + mentor_type_name: 'Job Preparation', + created_at: new Date(), + updated_at: new Date() + }, + { + mentor_type_name: 'Coding Skills', + created_at: new Date(), + updated_at: new Date() + }, + { + mentor_type_name: 'Productivity', + created_at: new Date(), + updated_at: new Date() + }, + { + mentor_type_name: 'Networking', + created_at: new Date(), + updated_at: new Date() + } + ], + {} + ); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.bulkDelete('Mentoring_types', null, {}); + } +}; diff --git a/database/seeders/20190902134855-demo-techJobs.js b/database/seeders/20190902134855-demo-techJobs.js new file mode 100644 index 0000000..83697b0 --- /dev/null +++ b/database/seeders/20190902134855-demo-techJobs.js @@ -0,0 +1,125 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.bulkInsert('Tech_jobs', [ + { + industry_id: 1, + tech_name: 'IT Professional', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Blockchain developer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Games developer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'UX Designer & UI Developer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'SQL Developer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Web Developer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Help Desk Support', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Software Engineer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Data Entry', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'DevOps Engineer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Network Administrator', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Information Security Analyst', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Artificial Intelligence Engineer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Cloud Architect', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'IT Manager', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Technical Specialist', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Application Developer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Chief Technology Officer', + created_at: new Date(), + updated_at: new Date() + }, + { + industry_id: 1, + tech_name: 'Chief Information Officer', + created_at: new Date(), + updated_at: new Date() + } + ]); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.bulkDelete('Tech_jobs', null, {}); + } +}; diff --git a/database/seeders/20190903092929-demo-socialMedias.js b/database/seeders/20190903092929-demo-socialMedias.js new file mode 100644 index 0000000..6b69acf --- /dev/null +++ b/database/seeders/20190903092929-demo-socialMedias.js @@ -0,0 +1,24 @@ +/* eslint-disable no-unused-vars */ +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.bulkInsert('Social_medias', [ + { + user_id: 1, + facebook: 'facebook.com', + created_at: new Date(), + updated_at: new Date() + }, + { + user_id: 2, + linkedin: 'facebookin.com', + facebook: 'facebooking.com', + created_at: new Date(), + updated_at: new Date() + } + ]); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.bulkDelete('Social_medias', null, {}); + } +}; diff --git a/index.js b/index.js index a075923..2e28d5b 100644 --- a/index.js +++ b/index.js @@ -3,19 +3,6 @@ const server = require('./server'); const PORT = process.env.PORT || 5000; -const serverVar = server.listen(PORT, () => { +server.listen(PORT, () => { console.log(`Server running at port ${PORT}`); }); - -function sum(...numbers) { - // eslint-disable-next-line no-restricted-globals - if (numbers.every(n => typeof n === 'number' && !isNaN(n))) { - return numbers.reduce((acc, item) => acc + item, 0); - } - throw Error('Contains invalid number'); -} - -module.exports = { - sum, - serverVar -}; diff --git a/package-lock.json b/package-lock.json index 24b58bb..2d2fc38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,6 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "dev": true, "requires": { "@babel/highlight": "^7.0.0" } @@ -17,7 +16,6 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", - "dev": true, "requires": { "@babel/code-frame": "^7.5.5", "@babel/generator": "^7.5.5", @@ -38,14 +36,12 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -53,7 +49,6 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", - "dev": true, "requires": { "@babel/types": "^7.5.5", "jsesc": "^2.5.1", @@ -65,8 +60,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -74,7 +68,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, "requires": { "@babel/helper-get-function-arity": "^7.0.0", "@babel/template": "^7.1.0", @@ -85,7 +78,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true, "requires": { "@babel/types": "^7.0.0" } @@ -93,14 +85,12 @@ "@babel/helper-plugin-utils": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", - "dev": true + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==" }, "@babel/helper-split-export-declaration": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, "requires": { "@babel/types": "^7.4.4" } @@ -109,7 +99,6 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", - "dev": true, "requires": { "@babel/template": "^7.4.4", "@babel/traverse": "^7.5.5", @@ -120,7 +109,6 @@ "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", - "dev": true, "requires": { "chalk": "^2.0.0", "esutils": "^2.0.2", @@ -130,14 +118,12 @@ "@babel/parser": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", - "dev": true + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==" }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0" } @@ -146,7 +132,6 @@ "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "@babel/parser": "^7.4.4", @@ -157,7 +142,6 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", - "dev": true, "requires": { "@babel/code-frame": "^7.5.5", "@babel/generator": "^7.5.5", @@ -174,7 +158,6 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", - "dev": true, "requires": { "esutils": "^2.0.2", "lodash": "^4.17.13", @@ -185,7 +168,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", - "dev": true, "requires": { "exec-sh": "^0.3.2", "minimist": "^1.2.0" @@ -194,8 +176,7 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } }, @@ -203,7 +184,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, "requires": { "@jest/source-map": "^24.9.0", "chalk": "^2.0.1", @@ -213,8 +193,7 @@ "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" } } }, @@ -222,7 +201,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", - "dev": true, "requires": { "@jest/console": "^24.7.1", "@jest/reporters": "^24.9.0", @@ -257,14 +235,12 @@ "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" } } }, @@ -272,7 +248,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", - "dev": true, "requires": { "@jest/fake-timers": "^24.9.0", "@jest/transform": "^24.9.0", @@ -284,7 +259,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "jest-message-util": "^24.9.0", @@ -295,7 +269,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", - "dev": true, "requires": { "@jest/environment": "^24.9.0", "@jest/test-result": "^24.9.0", @@ -323,8 +296,7 @@ "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" } } }, @@ -332,7 +304,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, "requires": { "callsites": "^3.0.0", "graceful-fs": "^4.1.15", @@ -343,7 +314,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, "requires": { "@jest/console": "^24.9.0", "@jest/types": "^24.9.0", @@ -354,7 +324,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", - "dev": true, "requires": { "@jest/test-result": "^24.9.0", "jest-haste-map": "^24.9.0", @@ -366,7 +335,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", - "dev": true, "requires": { "@babel/core": "^7.1.0", "@jest/types": "^24.9.0", @@ -389,8 +357,7 @@ "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" } } }, @@ -398,7 +365,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^1.1.1", @@ -444,7 +410,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.2.tgz", "integrity": "sha512-cfCCrFmiGY/yq0NuKNxIQvZFy9kY/1immpSpTngOnyIbD4+eJOG5mxphhHDv3CHL9GltO4GcKr54kGBg3RNdbg==", - "dev": true, "requires": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0", @@ -457,7 +422,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.0.2.tgz", "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", - "dev": true, "requires": { "@babel/types": "^7.0.0" } @@ -466,7 +430,6 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", - "dev": true, "requires": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -476,7 +439,6 @@ "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.7.tgz", "integrity": "sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==", - "dev": true, "requires": { "@babel/types": "^7.3.0" } @@ -501,14 +463,12 @@ "@types/istanbul-lib-coverage": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", - "dev": true + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==" }, "@types/istanbul-lib-report": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", "integrity": "sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg==", - "dev": true, "requires": { "@types/istanbul-lib-coverage": "*" } @@ -517,7 +477,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", - "dev": true, "requires": { "@types/istanbul-lib-coverage": "*", "@types/istanbul-lib-report": "*" @@ -543,14 +502,12 @@ "@types/stack-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", - "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", - "dev": true + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==" }, "@types/yargs": { "version": "13.0.2", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.2.tgz", "integrity": "sha512-lwwgizwk/bIIU+3ELORkyuOgDjCh7zuWDFqRtPPhhVgq9N1F7CvLNKg1TX4f2duwtKQ0p044Au9r1PLIXHrIzQ==", - "dev": true, "requires": { "@types/yargs-parser": "*" } @@ -558,14 +515,12 @@ "@types/yargs-parser": { "version": "13.0.0", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-wBlsw+8n21e6eTd4yVv8YD/E3xq0O6nNnJIquutAsFGE7EyMKz7W6RNT6BRu1SmdgmlCZ9tb0X+j+D6HGr8pZw==", - "dev": true + "integrity": "sha512-wBlsw+8n21e6eTd4yVv8YD/E3xq0O6nNnJIquutAsFGE7EyMKz7W6RNT6BRu1SmdgmlCZ9tb0X+j+D6HGr8pZw==" }, "abab": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", - "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", - "dev": true + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==" }, "abbrev": { "version": "1.1.1", @@ -591,7 +546,6 @@ "version": "4.3.3", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.3.tgz", "integrity": "sha512-vkR40VwS2SYO98AIeFvzWWh+xyc2qi9s7OoXSFEGIP/rOJKzjnhykaZJNnHdoq4BL2gGxI5EZOU16z896EYnOQ==", - "dev": true, "requires": { "acorn": "^6.0.1", "acorn-walk": "^6.0.1" @@ -600,8 +554,7 @@ "acorn": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", - "dev": true + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==" } } }, @@ -614,14 +567,12 @@ "acorn-walk": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", - "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", - "dev": true + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" }, "ajv": { "version": "6.10.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -678,8 +629,7 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "ansi-styles": { "version": "3.2.1", @@ -709,6 +659,26 @@ "normalize-path": "^2.1.1" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -736,8 +706,7 @@ "array-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", - "dev": true + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" }, "array-flatten": { "version": "1.1.1", @@ -769,7 +738,6 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, "requires": { "safer-buffer": "~2.1.0" } @@ -777,8 +745,7 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "assign-symbols": { "version": "1.0.0", @@ -788,8 +755,12 @@ "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + }, + "async": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.1.0.tgz", + "integrity": "sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ==" }, "async-each": { "version": "1.0.3", @@ -799,8 +770,7 @@ "async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "asynckit": { "version": "0.4.0", @@ -815,20 +785,17 @@ "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "babel-jest": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", - "dev": true, "requires": { "@jest/transform": "^24.9.0", "@jest/types": "^24.9.0", @@ -842,8 +809,7 @@ "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" } } }, @@ -851,7 +817,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "find-up": "^3.0.0", @@ -863,7 +828,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -872,7 +836,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -882,7 +845,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -891,7 +853,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -899,8 +860,7 @@ "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==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" } } }, @@ -908,7 +868,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", - "dev": true, "requires": { "@types/babel__traverse": "^7.0.6" } @@ -917,12 +876,20 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", - "dev": true, "requires": { "@babel/plugin-syntax-object-rest-spread": "^7.0.0", "babel-plugin-jest-hoist": "^24.9.0" } }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -978,15 +945,32 @@ } } }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, "requires": { "tweetnacl": "^0.14.3" } }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", @@ -1034,6 +1018,11 @@ } } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, "boxen": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", @@ -1121,14 +1110,12 @@ "browser-process-hrtime": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", - "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", - "dev": true + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==" }, "browser-resolve": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", - "dev": true, "requires": { "resolve": "1.1.7" }, @@ -1136,8 +1123,7 @@ "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" } } }, @@ -1145,22 +1131,57 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.0.tgz", "integrity": "sha512-8zsjWrQkkBoLK6uxASk1nJ2SKv97ltiGDo6A3wA0/yRPz+CwmEyDo0hUrhIuukG2JHpAl3bvFIixw2/3Hi0DOg==", - "dev": true, "requires": { "node-int64": "^0.4.0" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, "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", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "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", @@ -1182,6 +1203,31 @@ "unset-value": "^1.0.0" } }, + "caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "dev": true, + "requires": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + }, + "dependencies": { + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, "caller-callsite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", @@ -1211,14 +1257,12 @@ "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "camelize": { "version": "1.0.0", @@ -1229,7 +1273,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", - "dev": true, "requires": { "rsvp": "^4.8.4" } @@ -1242,8 +1285,7 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chalk": { "version": "2.4.2", @@ -1261,6 +1303,29 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "cheerio": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash.assignin": "^4.0.9", + "lodash.bind": "^4.1.4", + "lodash.defaults": "^4.0.1", + "lodash.filter": "^4.4.0", + "lodash.flatten": "^4.2.0", + "lodash.foreach": "^4.3.0", + "lodash.map": "^4.4.0", + "lodash.merge": "^4.4.0", + "lodash.pick": "^4.2.1", + "lodash.reduce": "^4.4.0", + "lodash.reject": "^4.4.0", + "lodash.some": "^4.4.0" + } + }, "chokidar": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz", @@ -1309,8 +1374,7 @@ "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, "class-utils": { "version": "0.3.6", @@ -1338,6 +1402,26 @@ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" }, + "cli-color": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", + "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "requires": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, "cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", @@ -1410,7 +1494,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, "requires": { "string-width": "^3.1.0", "strip-ansi": "^5.2.0", @@ -1420,20 +1503,17 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "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=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "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==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -1442,6 +1522,15 @@ } } }, + "cloudinary": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.14.0.tgz", + "integrity": "sha512-auJY4aD1UGnQTD2iy6kuTA+FJsqyrr9svG12WYSPAO6oRGRf+16UFDDBNuRMm37wj8Tyn8LyiED0b+Jha36ORA==", + "requires": { + "lodash": "^4.17.11", + "q": "^1.5.1" + } + }, "cls-bluebird": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", @@ -1454,8 +1543,7 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" }, "code-point-at": { "version": "1.1.0", @@ -1496,7 +1584,12 @@ "commander": { "version": "2.20.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, "component-emitter": { @@ -1509,6 +1602,26 @@ "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" + } + }, + "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==", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, "configstore": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", @@ -1571,7 +1684,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -1596,6 +1708,11 @@ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, + "core-js": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1650,6 +1767,49 @@ } } }, + "coveralls": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.6.tgz", + "integrity": "sha512-Pgh4v3gCI4T/9VijVrm8Ym5v0OgjvGLKj3zTUwkvsCiwqae/p6VLzpsFNjQS2i6ewV7ef+DjFJ5TSKxYt/mCrA==", + "dev": true, + "requires": { + "growl": "~> 1.10.0", + "js-yaml": "^3.13.1", + "lcov-parse": "^0.0.10", + "log-driver": "^1.2.7", + "minimist": "^1.2.0", + "request": "^2.86.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, "create-error-class": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", @@ -1658,11 +1818,20 @@ "capture-stack-trace": "^1.0.0" } }, + "cross-env": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.0.tgz", + "integrity": "sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.5", + "is-windows": "^1.0.0" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -1674,8 +1843,7 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -1684,26 +1852,48 @@ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + }, "cssom": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" }, "cssstyle": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", - "dev": true, "requires": { "cssom": "0.3.x" } }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -1717,7 +1907,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", - "dev": true, "requires": { "abab": "^2.0.0", "whatwg-mimetype": "^2.2.0", @@ -1728,7 +1917,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", - "dev": true, "requires": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", @@ -1737,6 +1925,15 @@ } } }, + "datauri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/datauri/-/datauri-2.0.0.tgz", + "integrity": "sha512-zS2HSf9pI5XPlNZgIqJg/wCJpecgU/HA6E/uv2EfaWnW1EiTGLfy/EexTIsC9c99yoCOTXlqeeWk4FkCSuO3/g==", + "requires": { + "image-size": "^0.7.3", + "mimer": "^1.0.0" + } + }, "date-fns": { "version": "1.30.1", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", @@ -1754,8 +1951,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", @@ -1776,14 +1972,21 @@ "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0" + } }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -1856,26 +2059,56 @@ "detect-newline": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", - "dev": true + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", "requires": { - "path-type": "^4.0.0" + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" }, "dependencies": { - "path-type": { - "version": "4.0.0", + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "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-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true @@ -1896,15 +2129,45 @@ "esutils": "^2.0.2" } }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, "domexception": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", - "dev": true, "requires": { "webidl-conversions": "^4.0.2" } }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, "dont-sniff-mimetype": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz", @@ -1937,17 +2200,47 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "ejs": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.2.tgz", + "integrity": "sha512-PcW2a0tyTuPHz3tWyYqtK6r1fZ3gp+3Sop8Ph+ZYN81Ob5rwmbHEzaqs10N3BEsaGTkh/ooniXK+WwszGlc2+Q==" + }, "elegant-spinner": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", @@ -1969,16 +2262,19 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, "requires": { "once": "^1.4.0" } }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } @@ -1987,7 +2283,6 @@ "version": "1.13.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", - "dev": true, "requires": { "es-to-primitive": "^1.2.0", "function-bind": "^1.1.1", @@ -2001,13 +2296,58 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", - "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" } }, + "es5-ext": { + "version": "0.10.50", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.50.tgz", + "integrity": "sha512-KMzZTPBkeQV/JcSQhI5/z6d9VWJ3EnQ194USTUwIYZ2ZbpN8+SGXQKt1h68EX44+qt+Fzr8DO17vnxrw7c3agw==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "^1.0.0" + } + }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2022,7 +2362,6 @@ "version": "1.12.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", - "dev": true, "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", @@ -2034,8 +2373,7 @@ "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" } } }, @@ -2276,31 +2614,36 @@ "estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "exec-sh": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.2.tgz", - "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==", - "dev": true + "integrity": "sha512-9sLAvzhI5nc8TpuQUh4ahMdCrWT00wPWz7j47/emR5+2qEfoZP5zzUXvx+vdx+H6ohhnsYC31iX04QLYJK8zTg==" }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, "requires": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -2314,8 +2657,7 @@ "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" }, "expand-brackets": { "version": "2.1.4", @@ -2366,7 +2708,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "ansi-styles": "^3.2.0", @@ -2535,14 +2876,12 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-diff": { "version": "1.2.0", @@ -2612,14 +2951,12 @@ "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fastq": { "version": "1.6.0", @@ -2634,7 +2971,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz", "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", - "dev": true, "requires": { "bser": "^2.0.0" } @@ -2712,6 +3048,71 @@ } } }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", @@ -2743,11 +3144,32 @@ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" }, + "foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "dev": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + } + } + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { "version": "2.3.3", @@ -2787,11 +3209,20 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "1.2.9", @@ -3277,8 +3708,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -3289,8 +3719,7 @@ "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==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-own-enumerable-property-symbols": { "version": "3.0.0", @@ -3308,7 +3737,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, "requires": { "pump": "^3.0.0" } @@ -3322,7 +3750,6 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, "requires": { "assert-plus": "^1.0.0" } @@ -3331,7 +3758,6 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3361,8 +3787,7 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, "globby": { "version": "10.0.1", @@ -3418,17 +3843,21 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, "handlebars": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", - "dev": true, "requires": { "neo-async": "^2.6.0", "optimist": "^0.6.1", @@ -3439,14 +3868,12 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dev": true, "requires": { "ajv": "^6.5.5", "har-schema": "^2.0.0" @@ -3456,7 +3883,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -3486,8 +3912,7 @@ "has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" }, "has-value": { "version": "1.0.0", @@ -3518,6 +3943,15 @@ } } }, + "hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "dev": true, + "requires": { + "is-stream": "^1.0.1" + } + }, "helmet": { "version": "3.20.0", "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.20.0.tgz", @@ -3571,8 +4005,7 @@ "hosted-git-info": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", - "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", - "dev": true + "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==" }, "hpkp": { "version": "2.0.0", @@ -3598,11 +4031,35 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", - "dev": true, "requires": { "whatwg-encoding": "^1.0.1" } }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", + "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -3626,7 +4083,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -3772,6 +4228,11 @@ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" }, + "image-size": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.7.4.tgz", + "integrity": "sha512-GqPgxs+VkOr12aWwjSkyRzf5atzObWpFtiRuDgxCl2I/SDpZOKZFRD3iIAeAN6/usmn8SeLWRt7a8JRYK0Whbw==" + }, "import-fresh": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", @@ -3791,7 +4252,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, "requires": { "pkg-dir": "^3.0.0", "resolve-cwd": "^2.0.0" @@ -3801,7 +4261,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -3810,7 +4269,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -3820,7 +4278,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -3829,7 +4286,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -3837,14 +4293,12 @@ "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==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "pkg-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, "requires": { "find-up": "^3.0.0" } @@ -3871,7 +4325,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -3912,7 +4365,6 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, "requires": { "loose-envify": "^1.0.0" } @@ -3943,8 +4395,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { "version": "1.0.1", @@ -3967,14 +4418,12 @@ "is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", - "dev": true + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, "requires": { "ci-info": "^2.0.0" } @@ -4000,8 +4449,7 @@ "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-descriptor": { "version": "0.1.6", @@ -4045,8 +4493,7 @@ "is-generator-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" }, "is-glob": { "version": "4.0.1", @@ -4147,8 +4594,7 @@ "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, "is-redirect": { "version": "1.0.0", @@ -4159,7 +4605,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, "requires": { "has": "^1.0.1" } @@ -4184,7 +4629,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", - "dev": true, "requires": { "has-symbols": "^1.0.0" } @@ -4192,8 +4636,7 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-windows": { "version": "1.0.2", @@ -4203,8 +4646,7 @@ "is-wsl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" }, "isarray": { "version": "1.0.0", @@ -4224,20 +4666,26 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul-lib-coverage": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==" + }, + "istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "dev": true, + "requires": { + "append-transform": "^1.0.0" + } }, "istanbul-lib-instrument": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", - "dev": true, "requires": { "@babel/generator": "^7.4.0", "@babel/parser": "^7.4.3", @@ -4252,7 +4700,6 @@ "version": "2.0.8", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", - "dev": true, "requires": { "istanbul-lib-coverage": "^2.0.5", "make-dir": "^2.1.0", @@ -4263,7 +4710,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -4274,7 +4720,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", - "dev": true, "requires": { "debug": "^4.1.1", "istanbul-lib-coverage": "^2.0.5", @@ -4287,7 +4732,6 @@ "version": "2.2.6", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", - "dev": true, "requires": { "handlebars": "^4.1.2" } @@ -4296,7 +4740,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", - "dev": true, "requires": { "import-local": "^2.0.0", "jest-cli": "^24.9.0" @@ -4306,7 +4749,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", - "dev": true, "requires": { "@jest/core": "^24.9.0", "@jest/test-result": "^24.9.0", @@ -4329,7 +4771,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "execa": "^1.0.0", @@ -4340,7 +4781,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", - "dev": true, "requires": { "@babel/core": "^7.1.0", "@jest/test-sequencer": "^24.9.0", @@ -4365,7 +4805,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", - "dev": true, "requires": { "chalk": "^2.0.1", "diff-sequences": "^24.9.0", @@ -4377,7 +4816,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", - "dev": true, "requires": { "detect-newline": "^2.1.0" } @@ -4386,7 +4824,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "chalk": "^2.0.1", @@ -4399,7 +4836,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", - "dev": true, "requires": { "@jest/environment": "^24.9.0", "@jest/fake-timers": "^24.9.0", @@ -4413,7 +4849,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", - "dev": true, "requires": { "@jest/environment": "^24.9.0", "@jest/fake-timers": "^24.9.0", @@ -4425,14 +4860,12 @@ "jest-get-type": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==" }, "jest-haste-map": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "anymatch": "^2.0.0", @@ -4452,7 +4885,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", - "dev": true, "requires": { "@babel/traverse": "^7.1.0", "@jest/environment": "^24.9.0", @@ -4476,7 +4908,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", - "dev": true, "requires": { "jest-get-type": "^24.9.0", "pretty-format": "^24.9.0" @@ -4486,7 +4917,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", - "dev": true, "requires": { "chalk": "^2.0.1", "jest-diff": "^24.9.0", @@ -4498,7 +4928,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "@jest/test-result": "^24.9.0", @@ -4513,8 +4942,7 @@ "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" } } }, @@ -4522,7 +4950,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, "requires": { "@jest/types": "^24.9.0" } @@ -4530,20 +4957,17 @@ "jest-pnp-resolver": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", - "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", - "dev": true + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==" }, "jest-regex-util": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", - "dev": true + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==" }, "jest-resolve": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "browser-resolve": "^1.11.3", @@ -4556,7 +4980,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "jest-regex-util": "^24.3.0", @@ -4567,7 +4990,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", - "dev": true, "requires": { "@jest/console": "^24.7.1", "@jest/environment": "^24.9.0", @@ -4594,7 +5016,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", - "dev": true, "requires": { "@jest/console": "^24.7.1", "@jest/environment": "^24.9.0", @@ -4624,22 +5045,19 @@ "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" } } }, "jest-serializer": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", - "dev": true + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==" }, "jest-snapshot": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", - "dev": true, "requires": { "@babel/types": "^7.0.0", "@jest/types": "^24.9.0", @@ -4660,7 +5078,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", - "dev": true, "requires": { "@jest/console": "^24.9.0", "@jest/fake-timers": "^24.9.0", @@ -4679,8 +5096,7 @@ "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" } } }, @@ -4688,7 +5104,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "camelcase": "^5.3.1", @@ -4702,7 +5117,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", - "dev": true, "requires": { "@jest/test-result": "^24.9.0", "@jest/types": "^24.9.0", @@ -4716,8 +5130,7 @@ "ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" } } }, @@ -4725,7 +5138,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", - "dev": true, "requires": { "merge-stream": "^2.0.0", "supports-color": "^6.1.0" @@ -4735,18 +5147,28 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, "requires": { "has-flag": "^3.0.0" } } } }, + "js-beautify": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.10.2.tgz", + "integrity": "sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ==", + "requires": { + "config-chain": "^1.1.12", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "mkdirp": "~0.5.1", + "nopt": "~4.0.1" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.13.1", @@ -4761,14 +5183,12 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsdom": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", - "dev": true, "requires": { "abab": "^2.0.0", "acorn": "^5.5.3", @@ -4801,34 +5221,29 @@ "acorn": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" } } }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -4839,14 +5254,12 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", - "dev": true, "requires": { "minimist": "^1.2.0" }, @@ -4854,8 +5267,39 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -4863,7 +5307,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -4871,6 +5314,39 @@ "verror": "1.10.0" } }, + "juice": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/juice/-/juice-5.2.0.tgz", + "integrity": "sha512-0l6GZmT3efexyaaay3SchKT5kG311N59TEFP5lfvEy0nz9SNqjx311plJ3b4jze7arsmDsiHQLh/xnAuk0HFTQ==", + "requires": { + "cheerio": "^0.22.0", + "commander": "^2.15.1", + "cross-spawn": "^6.0.5", + "deep-extend": "^0.6.0", + "mensch": "^0.3.3", + "slick": "^1.12.2", + "web-resource-inliner": "^4.3.1" + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -4879,8 +5355,7 @@ "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" }, "latest-version": { "version": "3.1.0", @@ -4890,23 +5365,26 @@ "package-json": "^4.0.0" } }, + "lcov-parse": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "dev": true + }, "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", - "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", - "dev": true + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -5228,10 +5706,121 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" + }, + "lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.filter": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", + "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + }, + "lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + }, + "lodash.reject": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", + "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=" + }, + "log-driver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", + "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", "dev": true }, "log-symbols": { @@ -5341,7 +5930,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -5360,11 +5948,27 @@ "yallist": "^2.1.2" } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "~0.10.2" + } + }, + "mailgen": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/mailgen/-/mailgen-2.0.8.tgz", + "integrity": "sha512-TuimMv6N6F5EG/JRz1Tmhk7uMBCUu+3V8uIVGduXyNu7M3EigKTl97Wu1pfsA8udOgcpdD7gDJHoWwbz9Jt8ig==", + "requires": { + "ejs": "^2.6.1", + "juice": "^5.2.0" + } + }, "make-dir": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, "requires": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -5373,14 +5977,12 @@ "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -5388,7 +5990,6 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", - "dev": true, "requires": { "tmpl": "1.0.x" } @@ -5411,16 +6012,44 @@ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "requires": { + "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" + } + }, + "mensch": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.3.tgz", + "integrity": "sha1-4gD/TdgjcX+OBWOzLj9UgfyiYrI=" + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + } + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "merge2": { "version": "1.2.4", @@ -5471,6 +6100,11 @@ "mime-db": "1.40.0" } }, + "mimer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimer/-/mimer-1.0.0.tgz", + "integrity": "sha512-4ZJvCzfcwsBgPbkKXUzGoVZMWjv8IDIygkGzVc7uUYhgnK0t2LmGxxjdgH1i+pn0/KQfB5F/VKUJlfyTSOFQjg==" + }, "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -5488,8 +6122,7 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mixin-deep": { "version": "1.3.2", @@ -5514,7 +6147,6 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" } @@ -5532,11 +6164,61 @@ "moment": ">= 2.9.0" } }, + "morgan": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", + "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "requires": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "multer": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz", + "integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, + "multer-storage-cloudinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/multer-storage-cloudinary/-/multer-storage-cloudinary-2.2.1.tgz", + "integrity": "sha1-0x8luPCVID8xyeVUwBrYxpGxqXQ=", + "requires": { + "run-parallel": "^1.1.6" + } + }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -5570,8 +6252,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "negotiator": { "version": "0.6.2", @@ -5581,37 +6262,48 @@ "neo-async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==" + }, + "nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", "dev": true }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" }, "nocache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz", "integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==" }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" }, "node-modules-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=" }, "node-notifier": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", - "dev": true, "requires": { "growly": "^1.3.0", "is-wsl": "^1.1.0", @@ -5623,11 +6315,15 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, + "nodemailer": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.3.0.tgz", + "integrity": "sha512-TEHBNBPHv7Ie/0o3HXnb7xrPSSQmH1dXwQKRaMKDBGt/ZN54lvDVujP6hKkO/vjkIYL9rK8kHSG11+G42Nhxuw==" + }, "nodemon": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.19.1.tgz", @@ -5661,18 +6357,18 @@ } }, "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "requires": { - "abbrev": "1" + "abbrev": "1", + "osenv": "^0.1.4" } }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -5683,8 +6379,7 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -5704,6 +6399,14 @@ "path-key": "^2.0.0" } }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -5713,14 +6416,95 @@ "nwsapi": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.1.4.tgz", - "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==", - "dev": true + "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==" + }, + "nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + } + } + }, + "oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { "version": "4.1.1", @@ -5758,8 +6542,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", @@ -5797,7 +6580,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", - "dev": true, "requires": { "define-properties": "^1.1.2", "es-abstract": "^1.5.1" @@ -5831,11 +6613,15 @@ "ee-first": "1.1.1" } }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -5859,7 +6645,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, "requires": { "minimist": "~0.0.1", "wordwrap": "~0.0.2" @@ -5868,8 +6653,7 @@ "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" } } }, @@ -5877,7 +6661,6 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, "requires": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.4", @@ -5887,17 +6670,29 @@ "wordwrap": "~1.0.0" } }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } }, "p-each-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", - "dev": true, "requires": { "p-reduce": "^1.0.0" } @@ -5934,8 +6729,7 @@ "p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", - "dev": true + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" }, "p-try": { "version": "1.0.0", @@ -5943,6 +6737,18 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, + "package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, "package-json": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", @@ -5961,44 +6767,154 @@ } } }, - "packet-reader": { + "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==" + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "passport": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.0.tgz", + "integrity": "sha1-xQlWkTR71a07XhgCOMORTRbwWBE=", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + } + }, + "passport-facebook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz", + "integrity": "sha512-K/qNzuFsFISYAyC1Nma4qgY/12V3RSLFdFVsPKXiKZt434wOvthFW1p7zKa1iQihQMRhaWorVE1o3Vi1o+ZgeQ==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-github": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/passport-github/-/passport-github-1.1.0.tgz", + "integrity": "sha1-jOHj/NYa11eOsd9ZWDnkrqEjVdQ=", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-google-oauth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth/-/passport-google-oauth-2.0.0.tgz", + "integrity": "sha512-JKxZpBx6wBQXX1/a1s7VmdBgwOugohH+IxCy84aPTZNq/iIPX6u7Mqov1zY7MKRz3niFPol0KJz8zPLBoHKtYA==", + "requires": { + "passport-google-oauth1": "1.x.x", + "passport-google-oauth20": "2.x.x" + } + }, + "passport-google-oauth1": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth1/-/passport-google-oauth1-1.0.0.tgz", + "integrity": "sha1-r3SoA99R7GRvZqRNgigr5vEI4Mw=", + "requires": { + "passport-oauth1": "1.x.x" + } + }, + "passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-jwt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/passport-jwt/-/passport-jwt-4.0.0.tgz", + "integrity": "sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==", + "requires": { + "jsonwebtoken": "^8.2.0", + "passport-strategy": "^1.0.0" + } + }, + "passport-linkedin": { "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==" + "resolved": "https://registry.npmjs.org/passport-linkedin/-/passport-linkedin-1.0.0.tgz", + "integrity": "sha1-4zAM8jL357S5VxDiOPC7eTa12Fo=", + "requires": { + "passport-oauth1": "1.x.x" + } }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, + "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": { - "callsites": "^3.0.0" + "passport-strategy": "1.x.x" } }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, + "passport-oauth1": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/passport-oauth1/-/passport-oauth1-1.1.0.tgz", + "integrity": "sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg=", "requires": { - "error-ex": "^1.2.0" + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "utils-merge": "1.x.x" } }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true + "passport-oauth2": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz", + "integrity": "sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "passport-twitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/passport-twitter/-/passport-twitter-1.0.4.tgz", + "integrity": "sha1-AaeZ4fdgvy3knyul+6MigvGJMtc=", + "requires": { + "passport-oauth1": "1.x.x", + "xtraverse": "0.1.x" + } }, "path-dirname": { "version": "1.0.2", @@ -6008,8 +6924,7 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", @@ -6029,8 +6944,7 @@ "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==", - "dev": true + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, "path-to-regexp": { "version": "0.1.7", @@ -6046,11 +6960,15 @@ "pify": "^2.0.0" } }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pg": { "version": "7.12.1", @@ -6132,7 +7050,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, "requires": { "node-modules-regexp": "^1.0.0" } @@ -6163,8 +7080,7 @@ "pn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", - "dev": true + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" }, "posix-character-classes": { "version": "0.1.1", @@ -6197,8 +7113,7 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "prepend-http": { "version": "1.0.4", @@ -6224,7 +7139,6 @@ "version": "24.9.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "dev": true, "requires": { "@jest/types": "^24.9.0", "ansi-regex": "^4.0.0", @@ -6247,12 +7161,16 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.2.1.tgz", "integrity": "sha512-VObPvJiWPhpZI6C5m60XOzTfnYg/xc/an+r9VYymj9WJW3B/DIH+REzjpAACPf8brwPeP+7vz3bIim3S+AaMjw==", - "dev": true, "requires": { "kleur": "^3.0.3", "sisteransi": "^1.0.3" } }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, "proxy-addr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", @@ -6270,8 +7188,7 @@ "psl": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz", - "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==", - "dev": true + "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==" }, "pstree.remy": { "version": "1.1.7", @@ -6282,7 +7199,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -6291,8 +7207,12 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, "qs": { "version": "6.5.2", @@ -6341,8 +7261,7 @@ "react-is": { "version": "16.9.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz", - "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==", - "dev": true + "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==" }, "read-pkg": { "version": "2.0.0", @@ -6393,7 +7312,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", - "dev": true, "requires": { "util.promisify": "^1.0.0" } @@ -6403,6 +7321,11 @@ "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz", "integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA==" }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -6435,6 +7358,15 @@ "rc": "^1.0.1" } }, + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "requires": { + "es6-error": "^4.0.1" + } + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -6454,7 +7386,6 @@ "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -6476,31 +7407,12 @@ "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - } } }, "request-promise-core": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", - "dev": true, "requires": { "lodash": "^4.17.11" } @@ -6509,7 +7421,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz", "integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==", - "dev": true, "requires": { "request-promise-core": "1.1.2", "stealthy-require": "^1.1.1", @@ -6519,20 +7430,17 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, "requires": { "path-parse": "^1.0.6" } @@ -6541,7 +7449,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, "requires": { "resolve-from": "^3.0.0" }, @@ -6549,8 +7456,7 @@ "resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" } } }, @@ -6598,7 +7504,6 @@ "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -6606,8 +7511,7 @@ "rsvp": { "version": "4.8.5", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", - "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", - "dev": true + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==" }, "run-async": { "version": "2.3.0", @@ -6627,8 +7531,7 @@ "run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" }, "rxjs": { "version": "6.5.2", @@ -6661,7 +7564,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", - "dev": true, "requires": { "@cnakazawa/watch": "^1.0.3", "anymatch": "^2.0.0", @@ -6677,16 +7579,14 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" } } }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "semver": { "version": "6.3.0", @@ -6757,9 +7657,9 @@ } }, "sequelize": { - "version": "5.15.1", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.15.1.tgz", - "integrity": "sha512-DCzzJYvJLMKnyf8G3at2A+yM9M2fSQmTmuOYIpCWM8Gjqx3XfgNTd1NkuyPWFoi1/d1AXQsN2VDPXkPczida8A==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-5.16.0.tgz", + "integrity": "sha512-1b2PNgxV3+HtaOCJ9gos4qQzvd8QEc5jz77MUxZg8+nqX4haSZWI7Rn0XzW1lPIRseKUXVHanyh/gqztsfJN+g==", "requires": { "bluebird": "^3.5.0", "cls-bluebird": "^2.1.0", @@ -6778,6 +7678,21 @@ "wkx": "^0.4.6" } }, + "sequelize-cli": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-5.5.0.tgz", + "integrity": "sha512-twVQ02alCpr2XvxNmpi32C48WZs6xHTH1OFTfTS5Meg3BVqOM8ghiZoml4FITFjlD8sAJSQjlAHTwqTbuolA6Q==", + "requires": { + "bluebird": "^3.5.3", + "cli-color": "^1.4.0", + "fs-extra": "^7.0.1", + "js-beautify": "^1.8.8", + "lodash": "^4.17.5", + "resolve": "^1.5.0", + "umzug": "^2.1.0", + "yargs": "^13.1.0" + } + }, "sequelize-pool": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-2.3.0.tgz", @@ -6797,8 +7712,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-value": { "version": "2.0.1", @@ -6842,14 +7756,66 @@ "shellwords": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" }, "shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, + "should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "requires": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "requires": { + "should-type": "^1.4.0" + } + }, + "should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "requires": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=" + }, + "should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "requires": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -6858,8 +7824,7 @@ "sisteransi": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.3.tgz", - "integrity": "sha512-SbEG75TzH8G7eVXFSN5f9EExILKfly7SUvVY5DhhYLvfhKqhDFY0OzevWa/zwak0RLRfWS5AvfMWpd9gJvr5Yg==", - "dev": true + "integrity": "sha512-SbEG75TzH8G7eVXFSN5f9EExILKfly7SUvVY5DhhYLvfhKqhDFY0OzevWa/zwak0RLRfWS5AvfMWpd9gJvr5Yg==" }, "slash": { "version": "3.0.0", @@ -6886,6 +7851,11 @@ } } }, + "slick": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz", + "integrity": "sha1-vQSN23TefRymkV+qSldXCzVQwtc=" + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -7004,8 +7974,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-resolve": { "version": "0.5.2", @@ -7023,7 +7992,6 @@ "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -7034,11 +8002,24 @@ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" }, + "spawn-wrap": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", + "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", + "dev": true, + "requires": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -7047,14 +8028,12 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -7063,8 +8042,7 @@ "spdx-license-ids": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" }, "split": { "version": "1.0.1", @@ -7092,7 +8070,6 @@ "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -7108,8 +8085,7 @@ "stack-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", - "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", - "dev": true + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==" }, "static-extend": { "version": "0.1.2", @@ -7138,8 +8114,12 @@ "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", - "dev": true + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" }, "string-argv": { "version": "0.3.0", @@ -7151,7 +8131,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", - "dev": true, "requires": { "astral-regex": "^1.0.0", "strip-ansi": "^4.0.0" @@ -7160,14 +8139,12 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, "requires": { "ansi-regex": "^3.0.0" } @@ -7208,7 +8185,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -7216,8 +8192,7 @@ "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" }, "strip-eof": { "version": "1.0.0", @@ -7289,8 +8264,7 @@ "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "table": { "version": "5.4.6", @@ -7372,7 +8346,6 @@ "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", - "dev": true, "requires": { "glob": "^7.1.3", "minimatch": "^3.0.4", @@ -7384,7 +8357,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -7393,7 +8365,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, "requires": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", @@ -7405,7 +8376,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -7415,7 +8385,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -7424,7 +8393,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -7432,14 +8400,12 @@ "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==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, "requires": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" @@ -7449,7 +8415,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, "requires": { "pify": "^3.0.0" } @@ -7457,14 +8422,12 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, "requires": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", @@ -7475,7 +8438,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", - "dev": true, "requires": { "find-up": "^3.0.0", "read-pkg": "^3.0.0" @@ -7492,8 +8454,7 @@ "throat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", - "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", - "dev": true + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=" }, "through": { "version": "2.3.8", @@ -7505,6 +8466,15 @@ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -7517,14 +8487,12 @@ "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", - "dev": true + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, "to-object-path": { "version": "0.3.0", @@ -7580,23 +8548,38 @@ "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" + } + } } }, "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } } }, "tr46": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -7604,8 +8587,7 @@ "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, "tslib": { "version": "1.10.0", @@ -7617,7 +8599,6 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -7625,14 +8606,17 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/type/-/type-1.0.3.tgz", + "integrity": "sha512-51IMtNfVcee8+9GJvj0spSuFcZHe9vSib6Xtgsny1Km9ugyz2mbS08I3rsUIRYgJohFRFU1160sgRodYz378Hg==" }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, "requires": { "prelude-ls": "~1.1.2" } @@ -7652,17 +8636,35 @@ "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.6.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", - "dev": true, "optional": true, "requires": { "commander": "~2.20.0", "source-map": "~0.6.1" } }, + "uid2": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" + }, + "umzug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.2.0.tgz", + "integrity": "sha512-xZLW76ax70pND9bx3wqwb8zqkFGzZIK8dIHD9WdNy/CrNfjWcwQgQkGCuUqcuwEBvUm+g07z+qWvY+pxDmMEEw==", + "requires": { + "babel-runtime": "^6.23.0", + "bluebird": "^3.5.3" + } + }, "undefsafe": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", @@ -7710,6 +8712,11 @@ "crypto-random-string": "^1.0.0" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -7797,7 +8804,6 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, "requires": { "punycode": "^2.1.0" } @@ -7829,7 +8835,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", - "dev": true, "requires": { "define-properties": "^1.1.2", "object.getownpropertydescriptors": "^2.0.3" @@ -7841,9 +8846,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, "v8-compile-cache": { "version": "2.1.0", @@ -7851,11 +8856,15 @@ "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, + "valid-data-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-2.0.0.tgz", + "integrity": "sha512-dyCZnv3aCey7yfTgIqdZanKl7xWAEEKCbgmR7SKqyK6QT/Z07ROactrgD1eA37C69ODRj7rNOjzKWVPh0EUjBA==" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -7866,6 +8875,11 @@ "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" }, + "validatorjs": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/validatorjs/-/validatorjs-3.15.1.tgz", + "integrity": "sha512-9hJWC4sYaEjf3a6MPKrERzRU69btS/pDy+t5IX8pRFqkI8UI2qj8nR3n2XlVzxRZMQGrf6HrtfDkoRcJavkLlg==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -7875,7 +8889,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -7886,7 +8899,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", - "dev": true, "requires": { "browser-process-hrtime": "^0.1.2" } @@ -7895,22 +8907,35 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", - "dev": true, "requires": { "makeerror": "1.0.x" } }, + "web-resource-inliner": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-4.3.3.tgz", + "integrity": "sha512-Qk19pohqZs3SoFUW4ZlOHlM8hsOnXhTpCrQ16b1qtJtKzJgO7NZLGP+/lcb2g3hWDQD39/LE/JYOn1Sjy7tn1A==", + "requires": { + "async": "^3.1.0", + "chalk": "^2.4.2", + "datauri": "^2.0.0", + "htmlparser2": "^3.9.2", + "lodash.unescape": "^4.0.1", + "request": "^2.78.0", + "safer-buffer": "^2.1.2", + "valid-data-url": "^2.0.0", + "xtend": "^4.0.2" + } + }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" }, "whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, "requires": { "iconv-lite": "0.4.24" } @@ -7918,14 +8943,12 @@ "whatwg-mimetype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" }, "whatwg-url": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", - "dev": true, "requires": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", @@ -7943,8 +8966,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "widest-line": { "version": "2.0.1", @@ -7994,14 +9016,12 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "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==", - "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -8011,20 +9031,17 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "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=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "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==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -8036,8 +9053,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "1.0.3", @@ -8062,7 +9078,6 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", - "dev": true, "requires": { "async-limiter": "~1.0.0" } @@ -8080,19 +9095,30 @@ "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=" }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, + "xtraverse": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xtraverse/-/xtraverse-0.1.0.tgz", + "integrity": "sha1-t0G60BjveNip0ug63gB7P3lZxzI=", + "requires": { + "xmldom": "0.1.x" + } + }, "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==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { "version": "2.1.2", @@ -8103,7 +9129,6 @@ "version": "13.3.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", - "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -8120,14 +9145,12 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -8135,14 +9158,12 @@ "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=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -8152,7 +9173,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -8161,7 +9181,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -8169,14 +9188,12 @@ "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==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "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==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -8189,7 +9206,6 @@ "version": "13.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/package.json b/package.json index 1bce2be..ee63b37 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,32 @@ "description": "Backend for Niyon application", "main": "index.js", "scripts": { + "test": "cross-env NODE_ENV=test jest --coverage --forceExit --detectOpenHandles", + "testcircleci": "cross-env NODE_ENV=test jest --coverage", "start": "node index.js", "start:dev": "nodemon index.js", - "test": "jest", "lint": "./node_modules/.bin/eslint . --fix", - "test:watch": "jest --watch" + "test:watch": "jest --watch", + "generator": "./node_modules/.bin/sequelize model:generate --name Mentees_chioces --attributes username:string", + "migration": "./node_modules/.bin/sequelize db:migrate", + "create:seeds": "./node_modules/.bin/sequelize seed:generate --name demo-mentors", + "dropMigration": "./node_modules/.bin/sequelize db:migrate:undo:all", + "undo:seed": "./node_modules/.bin/sequelize db:seed:undo:all", + "seed": "./node_modules/.bin/sequelize db:seed:all", + "pretest": "cross-env NODE_ENV=test npm run dropMigration && npm run migration && npm run undo:seed && npm run seed", + "coverall": "npm test && cat ./coverage/lcov.info | coveralls", + "coveralls": "nyc npm run testcircleci --coverageReporters=text-lcov | coveralls", + "test-ci": "nyc npm run testcircleci --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js" + }, + "jest": { + "collectCoverageFrom": [ + "api/**/*.js", + "!/node_modules/", + "!/api/middleware/authStrategies.js", + "!/api/middleware/cloudinaryImage.js", + "!/api/helpers/mail.js", + "!/_test_" + ] }, "repository": { "type": "git", @@ -21,21 +42,23 @@ "CI", "Express" ], - "author": "Ikechukwu Eze", + "author": "Niyon", "license": "MIT", "bugs": { "url": "https://github.com/labseu2-niyon/backend/issues" }, "homepage": "https://github.com/labseu2-niyon/backend#readme", "devDependencies": { + "coveralls": "^3.0.6", + "cross-env": "^5.2.0", "eslint": "^6.1.0", "eslint-config-airbnb-base": "^14.0.0", "eslint-config-prettier": "^6.0.0", "eslint-plugin-import": "^2.18.2", "eslint-plugin-prettier": "^3.1.0", "husky": "^3.0.4", - "jest": "^24.9.0", "lint-staged": "^9.2.3", + "nyc": "^14.1.1", "prettier": "1.18.2" }, "husky": { @@ -51,14 +74,37 @@ ] }, "dependencies": { + "bcryptjs": "^2.4.3", + "cloudinary": "^1.14.0", "cors": "^2.8.5", "dotenv": "^8.1.0", "express": "^4.17.1", "helmet": "^3.20.0", + "jest": "^24.9.0", + "jsonwebtoken": "^8.5.1", + "mailgen": "^2.0.8", + "moment": "^2.24.0", + "morgan": "^1.9.1", + "multer": "^1.4.2", + "multer-storage-cloudinary": "^2.2.1", + "node-fetch": "^2.6.0", + "nodemailer": "^6.3.0", "nodemon": "^1.19.1", + "passport": "^0.4.0", + "passport-facebook": "^3.0.0", + "passport-github": "^1.1.0", + "passport-google-oauth": "^2.0.0", + "passport-jwt": "^4.0.0", + "passport-linkedin": "^1.0.0", + "passport-local": "^1.0.0", + "passport-twitter": "^1.0.4", "pg": "^7.12.1", "pg-hstore": "^2.3.3", - "sequelize": "^5.15.1", - "supertest": "^4.0.2" + "sequelize": "^5.16.0", + "sequelize-cli": "^5.5.0", + "should": "^13.2.3", + "supertest": "^4.0.2", + "uuid": "^3.3.3", + "validatorjs": "^3.15.1" } -} +} \ No newline at end of file diff --git a/report.20190826.082443.18640.0.001.json b/report.20190826.082443.18640.0.001.json new file mode 100644 index 0000000..00aee9c --- /dev/null +++ b/report.20190826.082443.18640.0.001.json @@ -0,0 +1,442 @@ + +{ + "header": { + "event": "Allocation failed - JavaScript heap out of memory", + "trigger": "FatalError", + "filename": "report.20190826.082443.18640.0.001.json", + "dumpEventTime": "2019-08-26T08:24:43Z", + "dumpEventTimeStamp": "1566804283512", + "processId": 18640, + "commandLine": [ + "node", + "test.js" + ], + "nodejsVersion": "v11.13.0", + "wordSize": 64, + "arch": "x64", + "platform": "darwin", + "componentVersions": { + "node": "11.13.0", + "v8": "7.0.276.38-node.18", + "uv": "1.27.0", + "zlib": "1.2.11", + "brotli": "1.0.7", + "ares": "1.15.0", + "modules": "67", + "nghttp2": "1.34.0", + "napi": "4", + "llhttp": "1.1.1", + "http_parser": "2.8.0", + "openssl": "1.1.1b", + "cldr": "34.0", + "icu": "63.1", + "tz": "2018e", + "unicode": "11.0" + }, + "release": { + "name": "node", + "headersUrl": "https://nodejs.org/download/release/v11.13.0/node-v11.13.0-headers.tar.gz", + "sourceUrl": "https://nodejs.org/download/release/v11.13.0/node-v11.13.0.tar.gz" + }, + "osName": "Darwin", + "osRelease": "18.7.0", + "osVersion": "Darwin Kernel Version 18.7.0: Thu Jun 20 18:42:21 PDT 2019; root:xnu-4903.270.47~4/RELEASE_X86_64", + "osMachine": "x86_64", + "host": "Nmereginis-MacBook-Pro.local" + }, + "javascriptStack": { + "message": "No stack.", + "stack": [ + "Unavailable." + ] + }, + "nativeStack": [ + { + "pc": "0x000000010012a224", + "symbol": "report::TriggerNodeReport(v8::Isolate*, node::Environment*, char const*, char const*, std::__1::basic_string, std::__1::allocator > const&, v8::Local) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100066754", + "symbol": "node::OnFatalError(char const*, char const*) [/usr/local/bin/node]" + }, + { + "pc": "0x00000001001805d7", + "symbol": "v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100180578", + "symbol": "v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100443a74", + "symbol": "v8::internal::Heap::UpdateSurvivalStatistics(int) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100449b94", + "symbol": "v8::internal::Heap::SetUp() [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100429d89", + "symbol": "v8::internal::Factory::AllocateRawArray(int, v8::internal::PretenureFlag) [/usr/local/bin/node]" + }, + { + "pc": "0x0000000100429c40", + "symbol": "v8::internal::Factory::NewFixedArrayWithFiller(v8::internal::Heap::RootListIndex, int, v8::internal::Object*, v8::internal::PretenureFlag) [/usr/local/bin/node]" + }, + { + "pc": "0x00000001003e1c36", + "symbol": "v8::internal::(anonymous namespace)::ElementsAccessorBase >::ConvertElementsWithCapacity(v8::internal::Handle, v8::internal::Handle, v8::internal::ElementsKind, unsigned int, unsigned int, unsigned int, int) [/usr/local/bin/node]" + }, + { + "pc": "0x00000001003e05a1", + "symbol": "v8::internal::(anonymous namespace)::ElementsAccessorBase >::GrowCapacity(v8::internal::Handle, unsigned int) [/usr/local/bin/node]" + }, + { + "pc": "0x00000001005da994", + "symbol": "v8::internal::Runtime_GrowArrayElements(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node]" + }, + { + "pc": "0x000015627be4fc7d", + "symbol": "" + }, + { + "pc": "0x000015627beee462", + "symbol": "" + } + ], + "javascriptHeap": { + "totalMemory": 608714752, + "totalCommittedMemory": 606161280, + "usedMemory": 604378632, + "availableMemory": 920157392, + "memoryLimit": 1526909922, + "heapSpaces": { + "read_only_space": { + "memorySize": 524288, + "committedMemory": 42224, + "capacity": 515584, + "used": 33520, + "available": 482064 + }, + "new_space": { + "memorySize": 1048576, + "committedMemory": 17408, + "capacity": 1031168, + "used": 0, + "available": 1031168 + }, + "old_space": { + "memorySize": 2297856, + "committedMemory": 1667600, + "capacity": 2254208, + "used": 1613248, + "available": 640960 + }, + "code_space": { + "memorySize": 1048576, + "committedMemory": 846880, + "capacity": 563552, + "used": 563552, + "available": 0 + }, + "map_space": { + "memorySize": 536576, + "committedMemory": 328288, + "capacity": 245360, + "used": 245360, + "available": 0 + }, + "large_object_space": { + "memorySize": 603258880, + "committedMemory": 603258880, + "capacity": 1519926152, + "used": 601922952, + "available": 918003200 + }, + "new_large_object_space": { + "memorySize": 0, + "committedMemory": 0, + "capacity": 0, + "used": 0, + "available": 0 + } + } + }, + "resourceUsage": { + "userCpuSeconds": 1.16517, + "kernelCpuSeconds": 0.590619, + "cpuConsumptionPercent": 175.579, + "maxRss": 1074274500608, + "pageFaults": { + "IORequired": 282, + "IONotRequired": 451198 + }, + "fsActivity": { + "reads": 0, + "writes": 0 + } + }, + "libuv": [ + ], + "environmentVariables": { + "TERM_PROGRAM": "vscode", + "SHELL": "/bin/zsh", + "TERM": "xterm-256color", + "TMPDIR": "/var/folders/y5/v4m5kynd5q70b_8j9pzwr1880000gn/T/", + "Apple_PubSub_Socket_Render": "/private/tmp/com.apple.launchd.EZmF09tAJh/Render", + "TERM_PROGRAM_VERSION": "1.37.1", + "TERM_SESSION_ID": "62C90E5D-800D-48B2-8285-DBD736D76B9B", + "ZSH": "/Users/nmereginivincent/.oh-my-zsh", + "USER": "nmereginivincent", + "SSH_AUTH_SOCK": "/private/tmp/com.apple.launchd.vBAKuPCwBZ/Listeners", + "PAGER": "less", + "LSCOLORS": "Gxfxcxdxbxegedabagacad", + "PATH": "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/MacGPG2/bin", + "PWD": "/Users/nmereginivincent/Desktop/backend", + "XPC_FLAGS": "0x0", + "XPC_SERVICE_NAME": "0", + "SHLVL": "3", + "HOME": "/Users/nmereginivincent", + "LESS": "-R", + "LOGNAME": "nmereginivincent", + "LC_CTYPE": "UTF-8", + "__CF_USER_TEXT_ENCODING": "0x1F5:0:2", + "APPLICATION_INSIGHTS_NO_DIAGNOSTIC_CHANNEL": "true", + "LANG": "en_GB.UTF-8", + "COLORTERM": "truecolor", + "OLDPWD": "/Users/nmereginivincent/Desktop/backend", + "_": "/usr/local/bin/node" + }, + "userLimits": { + "core_file_size_blocks": { + "soft": 0, + "hard": "unlimited" + }, + "data_seg_size_kbytes": { + "soft": "unlimited", + "hard": "unlimited" + }, + "file_size_blocks": { + "soft": "unlimited", + "hard": "unlimited" + }, + "max_locked_memory_bytes": { + "soft": "unlimited", + "hard": "unlimited" + }, + "max_memory_size_kbytes": { + "soft": "unlimited", + "hard": "unlimited" + }, + "open_files": { + "soft": 10240, + "hard": "unlimited" + }, + "stack_size_bytes": { + "soft": 8388608, + "hard": 67104768 + }, + "cpu_time_seconds": { + "soft": "unlimited", + "hard": "unlimited" + }, + "max_user_processes": { + "soft": 709, + "hard": 1064 + }, + "virtual_memory_kbytes": { + "soft": "unlimited", + "hard": "unlimited" + } + }, + "sharedObjects": [ + "/usr/local/bin/node", + "/usr/local/opt/icu4c/lib/libicui18n.63.dylib", + "/usr/local/opt/icu4c/lib/libicuuc.63.dylib", + "/usr/local/opt/icu4c/lib/libicudata.63.1.dylib", + "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation", + "/usr/lib/libSystem.B.dylib", + "/usr/lib/libc++.1.dylib", + "/usr/lib/system/libcache.dylib", + "/usr/lib/system/libcommonCrypto.dylib", + "/usr/lib/system/libcompiler_rt.dylib", + "/usr/lib/system/libcopyfile.dylib", + "/usr/lib/system/libcorecrypto.dylib", + "/usr/lib/system/libdispatch.dylib", + "/usr/lib/system/libdyld.dylib", + "/usr/lib/system/libkeymgr.dylib", + "/usr/lib/system/liblaunch.dylib", + "/usr/lib/system/libmacho.dylib", + "/usr/lib/system/libquarantine.dylib", + "/usr/lib/system/libremovefile.dylib", + "/usr/lib/system/libsystem_asl.dylib", + "/usr/lib/system/libsystem_blocks.dylib", + "/usr/lib/system/libsystem_c.dylib", + "/usr/lib/system/libsystem_configuration.dylib", + "/usr/lib/system/libsystem_coreservices.dylib", + "/usr/lib/system/libsystem_darwin.dylib", + "/usr/lib/system/libsystem_dnssd.dylib", + "/usr/lib/system/libsystem_info.dylib", + "/usr/lib/system/libsystem_m.dylib", + "/usr/lib/system/libsystem_malloc.dylib", + "/usr/lib/system/libsystem_networkextension.dylib", + "/usr/lib/system/libsystem_notify.dylib", + "/usr/lib/system/libsystem_sandbox.dylib", + "/usr/lib/system/libsystem_secinit.dylib", + "/usr/lib/system/libsystem_kernel.dylib", + "/usr/lib/system/libsystem_platform.dylib", + "/usr/lib/system/libsystem_pthread.dylib", + "/usr/lib/system/libsystem_symptoms.dylib", + "/usr/lib/system/libsystem_trace.dylib", + "/usr/lib/system/libunwind.dylib", + "/usr/lib/system/libxpc.dylib", + "/usr/lib/libobjc.A.dylib", + "/usr/lib/libc++abi.dylib", + "/usr/lib/libDiagnosticMessagesClient.dylib", + "/usr/lib/libicucore.A.dylib", + "/usr/lib/libz.1.dylib", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices", + "/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics", + "/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO", + "/System/Library/Frameworks/ColorSync.framework/Versions/A/ColorSync", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/ATS", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ColorSyncLegacy.framework/Versions/A/ColorSyncLegacy", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/HIServices.framework/Versions/A/HIServices", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/LangAnalysis.framework/Versions/A/LangAnalysis", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/PrintCore", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/QD.framework/Versions/A/QD", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesis", + "/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLight", + "/System/Library/Frameworks/IOSurface.framework/Versions/A/IOSurface", + "/usr/lib/libxml2.2.dylib", + "/System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate", + "/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation", + "/usr/lib/libcompression.dylib", + "/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration", + "/System/Library/Frameworks/CoreDisplay.framework/Versions/A/CoreDisplay", + "/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", + "/System/Library/Frameworks/Metal.framework/Versions/A/Metal", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Versions/A/MetalPerformanceShaders", + "/System/Library/PrivateFrameworks/MultitouchSupport.framework/Versions/A/MultitouchSupport", + "/System/Library/Frameworks/Security.framework/Versions/A/Security", + "/System/Library/Frameworks/QuartzCore.framework/Versions/A/QuartzCore", + "/usr/lib/libbsm.0.dylib", + "/usr/lib/liblzma.5.dylib", + "/usr/lib/libauto.dylib", + "/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration", + "/usr/lib/libarchive.2.dylib", + "/usr/lib/liblangid.dylib", + "/usr/lib/libCRFSuite.dylib", + "/usr/lib/libenergytrace.dylib", + "/usr/lib/system/libkxld.dylib", + "/System/Library/PrivateFrameworks/AppleFSCompression.framework/Versions/A/AppleFSCompression", + "/usr/lib/libOpenScriptingUtil.dylib", + "/usr/lib/libcoretls.dylib", + "/usr/lib/libcoretls_cfhelpers.dylib", + "/usr/lib/libpam.2.dylib", + "/usr/lib/libsqlite3.dylib", + "/usr/lib/libxar.1.dylib", + "/usr/lib/libbz2.1.0.dylib", + "/usr/lib/libnetwork.dylib", + "/usr/lib/libapple_nghttp2.dylib", + "/usr/lib/libpcap.A.dylib", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/FSEvents.framework/Versions/A/FSEvents", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/CarbonCore.framework/Versions/A/CarbonCore", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/Metadata.framework/Versions/A/Metadata", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/OSServices.framework/Versions/A/OSServices", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SearchKit.framework/Versions/A/SearchKit", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/AE", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/LaunchServices", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/DictionaryServices.framework/Versions/A/DictionaryServices", + "/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/SharedFileList.framework/Versions/A/SharedFileList", + "/System/Library/Frameworks/NetFS.framework/Versions/A/NetFS", + "/System/Library/PrivateFrameworks/NetAuth.framework/Versions/A/NetAuth", + "/System/Library/PrivateFrameworks/login.framework/Versions/A/Frameworks/loginsupport.framework/Versions/A/loginsupport", + "/System/Library/PrivateFrameworks/TCC.framework/Versions/A/TCC", + "/System/Library/PrivateFrameworks/CoreNLP.framework/Versions/A/CoreNLP", + "/System/Library/PrivateFrameworks/MetadataUtilities.framework/Versions/A/MetadataUtilities", + "/usr/lib/libmecabra.dylib", + "/usr/lib/libmecab.1.0.0.dylib", + "/usr/lib/libgermantok.dylib", + "/usr/lib/libThaiTokenizer.dylib", + "/usr/lib/libChineseTokenizer.dylib", + "/usr/lib/libiconv.2.dylib", + "/usr/lib/libcharset.1.dylib", + "/System/Library/PrivateFrameworks/LanguageModeling.framework/Versions/A/LanguageModeling", + "/System/Library/PrivateFrameworks/CoreEmoji.framework/Versions/A/CoreEmoji", + "/System/Library/PrivateFrameworks/Lexicon.framework/Versions/A/Lexicon", + "/System/Library/PrivateFrameworks/LinguisticData.framework/Versions/A/LinguisticData", + "/usr/lib/libcmph.dylib", + "/System/Library/Frameworks/CoreData.framework/Versions/A/CoreData", + "/System/Library/Frameworks/OpenDirectory.framework/Versions/A/Frameworks/CFOpenDirectory.framework/Versions/A/CFOpenDirectory", + "/System/Library/PrivateFrameworks/APFS.framework/Versions/A/APFS", + "/usr/lib/libutil.dylib", + "/System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement", + "/System/Library/PrivateFrameworks/BackgroundTaskManagement.framework/Versions/A/BackgroundTaskManagement", + "/usr/lib/libxslt.1.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vImage.framework/Versions/A/vImage", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvMisc.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libvDSP.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLinearAlgebra.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparseBLAS.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libQuadrature.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBNNS.dylib", + "/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libSparse.dylib", + "/System/Library/PrivateFrameworks/GPUWrangler.framework/Versions/A/GPUWrangler", + "/System/Library/PrivateFrameworks/IOAccelerator.framework/Versions/A/IOAccelerator", + "/System/Library/PrivateFrameworks/IOPresentment.framework/Versions/A/IOPresentment", + "/System/Library/PrivateFrameworks/DSExternalDisplay.framework/Versions/A/DSExternalDisplay", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreFSCache.dylib", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSCore.framework/Versions/A/MPSCore", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSImage.framework/Versions/A/MPSImage", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSNeuralNetwork.framework/Versions/A/MPSNeuralNetwork", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSMatrix.framework/Versions/A/MPSMatrix", + "/System/Library/Frameworks/MetalPerformanceShaders.framework/Frameworks/MPSRayIntersector.framework/Versions/A/MPSRayIntersector", + "/System/Library/PrivateFrameworks/MetalTools.framework/Versions/A/MetalTools", + "/System/Library/PrivateFrameworks/AggregateDictionary.framework/Versions/A/AggregateDictionary", + "/usr/lib/libMobileGestalt.dylib", + "/System/Library/Frameworks/CoreImage.framework/Versions/A/CoreImage", + "/System/Library/Frameworks/CoreVideo.framework/Versions/A/CoreVideo", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL", + "/System/Library/PrivateFrameworks/GraphVisualizer.framework/Versions/A/GraphVisualizer", + "/System/Library/PrivateFrameworks/FaceCore.framework/Versions/A/FaceCore", + "/System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL", + "/usr/lib/libFosl_dynamic.dylib", + "/System/Library/PrivateFrameworks/OTSVG.framework/Versions/A/OTSVG", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontParser.dylib", + "/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/ATS.framework/Versions/A/Resources/libFontRegistry.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJPEG.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libTIFF.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libPng.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libGIF.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libJP2.dylib", + "/System/Library/Frameworks/ImageIO.framework/Versions/A/Resources/libRadiance.dylib", + "/System/Library/PrivateFrameworks/AppleJPEG.framework/Versions/A/AppleJPEG", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGFXShared.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLU.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGLImage.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCVMSPluginSupport.dylib", + "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libCoreVMClient.dylib", + "/usr/lib/libcups.2.dylib", + "/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos", + "/System/Library/Frameworks/GSS.framework/Versions/A/GSS", + "/usr/lib/libresolv.9.dylib", + "/System/Library/PrivateFrameworks/Heimdal.framework/Versions/A/Heimdal", + "/usr/lib/libheimdal-asn1.dylib", + "/System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory", + "/System/Library/PrivateFrameworks/CommonAuth.framework/Versions/A/CommonAuth", + "/System/Library/Frameworks/SecurityFoundation.framework/Versions/A/SecurityFoundation", + "/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio", + "/System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox", + "/System/Library/PrivateFrameworks/AppleSauce.framework/Versions/A/AppleSauce", + "/System/Library/PrivateFrameworks/AssertionServices.framework/Versions/A/AssertionServices", + "/System/Library/PrivateFrameworks/BaseBoard.framework/Versions/A/BaseBoard" + ] +} \ No newline at end of file diff --git a/server.js b/server.js index bceb727..0c730ea 100644 --- a/server.js +++ b/server.js @@ -1,18 +1,42 @@ const express = require('express'); +const passport = require('passport'); const cors = require('cors'); const helmet = require('helmet'); +const logger = require('morgan'); const apiRouter = require('./api'); +// const keys = require('./config/secret'); +// const jwt = require('./api/helpers/jwt'); +const github = require('./api/middleware/authStrategies'); const server = express(); server.use(helmet()); server.use(cors()); +server.use(logger('dev')); server.use(express.json()); +server.use(passport.initialize()); server.use('/api', apiRouter); +passport.use(github.githubStrategy()); -server.get('/', (_, res) => { - res.status(200).json('API endpoints exposed at /api'); +server.get('/', async (_, res) => { + // const user = { + // id: 1, + // username: 'john' + // }; + // const token = await jwt.generateToken(user); + res.status(200).json(`API endpoints exposed at /api`); +}); + +server.all('*', (req, res) => { + res.status(404).json({ + message: "This endpoint doesn't exists" + }); +}); + +// eslint-disable-next-line no-unused-vars +server.use(function errors(err, req, res, next) { + res.status(500).json({ err }); }); module.exports = server;