From f8c035c29253f030e9b7a318be6f582d21888fb3 Mon Sep 17 00:00:00 2001 From: Alina L Date: Sun, 23 Aug 2020 11:38:32 -0700 Subject: [PATCH 01/56] docs(contributing): move readme directions to own file (#61) --- CONTRIBUTING.md | 42 ++++++++++++++++++++++++++++++------------ README.md | 35 ++--------------------------------- 2 files changed, 32 insertions(+), 45 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b063bcb..8a1c81e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,15 +1,33 @@ -### Volunteering: +# Contributing -If you would like to contribute to the curriculum, please [sign up here](https://docs.google.com/forms/d/e/1FAIpQLSeW0mo-Dpsig70374UEPvzexpas-31Ost_HsFwm0kjNOxtbtg/viewform?c=0&w=1), then choose a to-do issue in the Projects tab above. +We would love your help! See the projects tab above for open to-do items that need some attention. -**Get started:** -- Click a "to-do" issue link and add yourself as the assignee, and pull it into the "in progress" column. (You'll need a github account to comment. If you know someone connected to Techtonica, they may be able to add you to our slack channel.) -- If it is in the "to-do" column, that means it is available. You are welcome to message questions to past assignees that may still show on the issue. - -**While working:** -- Comment in the issue if you have a question, and add the "question" tag to help get our attention. -- People are welcome to team up on an issue. If you see someone is already assigned but you want to help, leave the other assignee a message on the issue about collaborating. -- Please note the due date! Any amount of help is appreciated, but if the deadline comes and you won't be able to complete it, please leave a comment about your progress and unassign yourself from the issue so someone else can pick it up. If you forked the repo, go ahead and make a pull request with what you have, and transfer ownership of a copied slideshow to techtonicaorg@gmail.com. +Try the current version of the app [here](https://techtonica.github.io/keyboard-shortcuts-practice/). -**Completed curriculum:** -- Place a "completed" label on the issue once you've completed it, and leave comments about your work if you like. Grazie Mille!! +### Prerequisites +Prepare for contributing by following these beginner-friendly steps. + +1. [First, sign up here](https://docs.google.com/forms/d/e/1FAIpQLSeW0mo-Dpsig70374UEPvzexpas-31Ost_HsFwm0kjNOxtbtg/viewform?c=0&w=1). As a Nonprofit organization, we need this from volunteers. +1. Make sure you have created a [GitHub account](https://github.com/join), and are signed in. +1. Reach out to one of Techtonica's admin and send us your username so we can add you as a contributor. +1. Fork this repo by clicking the "fork" button in the upper-right corner of this page. +1. Choose a directory on your machine where you plan to store Github Projects. Open your terminal and `cd` to that directory. +1. Clone the project by running `git clone https://github.com//keyboard-shortcuts-practice.git` in your terminal, replacing `` with your account name. (Learn more about [Fork, Clone and Remote](https://github.com/anitab-org/mentorship-android/wiki/Fork%2C-Clone-%26-Remote).) +1. Run `cd keyboard-shortcuts-practice` to get into the root directory. +1. Run `git pull` to make sure you have the latest changes. +1. Run `git checkout backend` to go to the backend feature branch. This is the *only* branch that we will be working in. +1. Follow [the steps to run the project locally](/README.md/#running-the-project). +1. Run `git remote add upstream https://github.com/Techtonica/keyboard-shortcuts-practice.git`. This is so that you can refer to the original project owned by Techtonica as the `upstream` version. +1. Run `git remove -v` to test that you can get updates from Techtonica's repo. [You should see something like this](https://github.com/anitab-org/mentorship-android/wiki/Fork,-Clone-&-Remote#remote). If it shows an error that you don't have permission, contact a Tectonica admin. You can still get started without this part, but you'll need it soon. + +### Get started +1. Choose an issue in the "To Do" column of [this board](https://github.com/Techtonica/keyboard-shortcuts-practice/projects/4). +1. Leave a comment that you would like to pick up the issue. +1. Read the description, and make sure to ask questions about anything that is unclear. +1. Start on your forked repo's `backend` branch with `git checkout backend`. +1. Make sure you have the latest version of the project with `git pull upstream/backend`. +1. Create a new branch with `git checkout -b `. The name should include the issue number and the topic you're working in. For example, if its about adding a GET request, your command could be `git checkout -b add-get-request`. +1. Make and commit your changes on this new branch, and make a PR when you're ready. [Here are some directions on the process](http://www.dasblinkenlichten.com/how-to-create-a-github-pull-request-pr/). +1. When creating your PR, be sure to make your pull request to the `backend` feature branch: + making a pull request to the backend branch +1. See your pull requests here: https://github.com/Techtonica/keyboard-shortcuts-practice/pulls diff --git a/README.md b/README.md index edadff0..0ba302e 100644 --- a/README.md +++ b/README.md @@ -24,39 +24,8 @@ Our goal for the backend project is to create a persistant app where users can s If the browser shows ERR_INVALID_REDIRECT either add '/index.html' to the url ('http://127.0.0.1:8080/index.html') or downgrade your http-server version by running 'npm install -g http-server@0.9.0'. -## Contributing - -We would love your help! See the projects tab above for open to-do items that need some attention. - -Try the current version of the app [here](https://techtonica.github.io/keyboard-shortcuts-practice/). - -### Prerequisites -Prepare for contributing by following these beginner-friendly steps. - -1. [First, sign up here](https://docs.google.com/forms/d/e/1FAIpQLSeW0mo-Dpsig70374UEPvzexpas-31Ost_HsFwm0kjNOxtbtg/viewform?c=0&w=1). As a Nonprofit organization, we need this from volunteers. -1. Make sure you have created a [GitHub account](https://github.com/join), and are signed in. -1. Reach out to one of Techtonica's admin and send us your username so we can add you as a contributor. -1. Fork this repo by clicking the "fork" button in the upper-right corner of this page. -1. Choose a directory on your machine where you plan to store Github Projects. Open your terminal and `cd` to that directory. -1. Clone the project by running `git clone https://github.com//keyboard-shortcuts-practice.git` in your terminal, replacing `` with your account name. (Learn more about [Fork, Clone and Remote](https://github.com/anitab-org/mentorship-android/wiki/Fork%2C-Clone-%26-Remote).) -1. Run `cd keyboard-shortcuts-practice` to get into the root directory. -1. Run `git pull` to make sure you have the latest changes. -1. Run `git checkout backend` to go to the backend feature branch. This is the *only* branch that we will be working in. -1. Follow [the steps to run the project locally](#running-the-project). -1. Run `git remote add upstream https://github.com/Techtonica/keyboard-shortcuts-practice.git`. This is so that you can refer to the original project owned by Techtonica as the `upstream` version. -1. Run `git remove -v` to test that you can get updates from Techtonica's repo. [You should see something like this](https://github.com/anitab-org/mentorship-android/wiki/Fork,-Clone-&-Remote#remote). If it shows an error that you don't have permission, contact a Tectonica admin. You can still get started without this part, but you'll need it soon. - -### Get started -1. Choose an issue in the "To Do" column of [this board](https://github.com/Techtonica/keyboard-shortcuts-practice/projects/4). -1. Leave a comment that you would like to pick up the issue. -1. Read the description, and make sure to ask questions about anything that is unclear. -1. Start on your forked repo's `backend` branch with `git checkout backend`. -1. Make sure you have the latest version of the project with `git pull upstream/backend`. -1. Create a new branch with `git checkout -b `. The name should include the issue number and the topic you're working in. For example, if its about adding a GET request, your command could be `git checkout -b add-get-request`. -1. Make and commit your changes on this new branch, and make a PR when you're ready. [Here are some directions on the process](http://www.dasblinkenlichten.com/how-to-create-a-github-pull-request-pr/). -1. When creating your PR, be sure to make your pull request to the `backend` feature branch: - making a pull request to the backend branch -1. See your pull requests here: https://github.com/Techtonica/keyboard-shortcuts-practice/pulls +## Contributing / Volunteering +Go to [CONTRIBUTING.md](/CONTRIBUTING.md). ### Creative Commons Open-Source License This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode). From 7d1819fcbd580caca7a944898bb49c09a5ffbdc5 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Tue, 15 Sep 2020 15:09:25 -0400 Subject: [PATCH 02/56] docs: Resolve a typo with commands (#87) --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8a1c81e..88cfe81 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,14 +18,14 @@ Prepare for contributing by following these beginner-friendly steps. 1. Run `git checkout backend` to go to the backend feature branch. This is the *only* branch that we will be working in. 1. Follow [the steps to run the project locally](/README.md/#running-the-project). 1. Run `git remote add upstream https://github.com/Techtonica/keyboard-shortcuts-practice.git`. This is so that you can refer to the original project owned by Techtonica as the `upstream` version. -1. Run `git remove -v` to test that you can get updates from Techtonica's repo. [You should see something like this](https://github.com/anitab-org/mentorship-android/wiki/Fork,-Clone-&-Remote#remote). If it shows an error that you don't have permission, contact a Tectonica admin. You can still get started without this part, but you'll need it soon. +1. Run `git remote -v` to test that you can get updates from Techtonica's repo. [You should see something like this](https://github.com/anitab-org/mentorship-android/wiki/Fork,-Clone-&-Remote#remote). If it shows an error that you don't have permission, contact a Tectonica admin. You can still get started without this part, but you'll need it soon. ### Get started 1. Choose an issue in the "To Do" column of [this board](https://github.com/Techtonica/keyboard-shortcuts-practice/projects/4). 1. Leave a comment that you would like to pick up the issue. 1. Read the description, and make sure to ask questions about anything that is unclear. 1. Start on your forked repo's `backend` branch with `git checkout backend`. -1. Make sure you have the latest version of the project with `git pull upstream/backend`. +1. Make sure you have the latest version of the project with `git pull upstream backend` or `git merge upstream/backend`. 1. Create a new branch with `git checkout -b `. The name should include the issue number and the topic you're working in. For example, if its about adding a GET request, your command could be `git checkout -b add-get-request`. 1. Make and commit your changes on this new branch, and make a PR when you're ready. [Here are some directions on the process](http://www.dasblinkenlichten.com/how-to-create-a-github-pull-request-pr/). 1. When creating your PR, be sure to make your pull request to the `backend` feature branch: From 0899a1f8d4c1028d076c2f1a94f6f63093205fcb Mon Sep 17 00:00:00 2001 From: Sraddhanjali Acharya Date: Thu, 24 Sep 2020 10:24:17 -0500 Subject: [PATCH 03/56] docs: test commit Co-authored-by: tilaprimera --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0ba302e..47a1da3 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,8 @@ We discovered that our participants need an app similar to typing practice websi This project should train and test users to use the quicker keyboard shortcuts instead of a mouse and the GUI. The app gets more challenging as you progress through the commands. -Our goal for the backend project is to create a persistant app where users can sign in, practice with the app, and save their progress. That way, the next time they sign in, they can pick up where they left off rather than starting at the beginning. +Our goal for the backend project is to create a persistent app where users +can sign in, practice with the app, and save their progress. That way, the next time they sign in, they can pick up where they left off rather than starting at the beginning. ## Running the project From 4efcea91aaf1c8fa7dd01e2c34031c1f40cabfbb Mon Sep 17 00:00:00 2001 From: Bill DePhillips <355438+vegetabill@users.noreply.github.com> Date: Wed, 30 Sep 2020 18:56:44 -0700 Subject: [PATCH 04/56] Resolves #65 - Finish ORM Setup (#91) * Fixes #65 - Finish ORM Setup - Ensure we can connect to the DB before launching Express - Use sqlite for normal dev mode; postgres for production - Upgrade sequelize and postgres npm packages since the versions we were using hung trying to connect to pg - Use the sequelize.sync functionality to automatically setup any table(s) * Allow either type of DB in development mode - in dev mode, have default DB_URL of sqlite - in prod, DB_URL must be specified * fix .gitignore to have correct sqlite db name * clean up package.json scripts --- .env.example | 1 + .gitignore | 2 +- JS/config.js | 20 +- JS/orm.js | 51 +- app.js | 31 +- package-lock.json | 2722 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 18 +- 7 files changed, 2802 insertions(+), 43 deletions(-) create mode 100644 .env.example create mode 100644 package-lock.json diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..8bf93a9 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +DB_URL=dev mode defaults to sqlite (so this is not needed) diff --git a/.gitignore b/.gitignore index 5626784..a954538 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .DS_Store .env node_modules/ -package-lock.json +dev-db.sqlite \ No newline at end of file diff --git a/JS/config.js b/JS/config.js index 20b162e..13a5dd2 100644 --- a/JS/config.js +++ b/JS/config.js @@ -1 +1,19 @@ -exports.URL = process.env.URL; \ No newline at end of file +require("dotenv").config(); + +const { DB_URL, NODE_ENV } = process.env; + +const isProduction = () => NODE_ENV === "production"; +const isDevelopment = () => NODE_ENV === "development"; + +const getDefaultDbUrl = () => { + if (isDevelopment()) { + return "sqlite:dev-db.sqlite"; + } + throw new Error("DB_URL must be specified in production mode"); +}; + +module.exports = { + isProduction, + isDevelopment, + DB_URL: DB_URL || getDefaultDbUrl(), +}; diff --git a/JS/orm.js b/JS/orm.js index 52b2e25..26b47f1 100644 --- a/JS/orm.js +++ b/JS/orm.js @@ -1,31 +1,34 @@ -// access config/env variables -//var config = require("./config.js"); -require('dotenv').config(); -console.log(`${process.env.URL}`); - -// setting up ORM -var Sequelize = require('sequelize'); -var sequelize = new Sequelize(`${process.env.URL}`); +const Sequelize = require("sequelize"); +const { DB_URL } = require("./config.js"); +const sequelize = new Sequelize(DB_URL); // define basic model for a user const Model = Sequelize.Model; class User extends Model {} -User.init({ - uid: Sequelize.INTEGER, - q_number: Sequelize.STRING, - last_login: Sequelize.DATE -}, { sequelize, modelName: 'user' }); +User.init( + { + q_number: Sequelize.STRING, + last_login: Sequelize.DATE, + id: { + type: Sequelize.STRING, + primaryKey: true, + }, + }, + { + sequelize, + modelName: "user", + createdAt: "created_at", + updatedAt: "updated_at", + } +); -// testing database connection -sequelize - .authenticate() - .then(() => { - console.log('Connection has been established successfully.'); - }) - .catch(err => { - console.error('Unable to connect to the database:', err); -}); +const connectToDb = async () => { + await sequelize.authenticate(); + await sequelize.sync(); +}; -// TODO: make User model accessible from other files -// export { User }; \ No newline at end of file +module.exports = { + User, + connectToDb, +}; diff --git a/app.js b/app.js index f7a7b3d..371eda2 100644 --- a/app.js +++ b/app.js @@ -1,26 +1,33 @@ -const path = require('path'); -const morgan = require('morgan'); +const path = require("path"); +const morgan = require("morgan"); const express = require("express"); const bodyParser = require("body-parser"); +const { connectToDb } = require("./JS/orm"); const app = express(); -app.use(morgan('dev')); //morgan gives us useful logging +app.use(morgan("dev")); //morgan gives us useful logging -require('ejs'); -app.set('view engine', 'ejs'); -app.set('views', path.join(__dirname, 'views')); +require("ejs"); +app.set("view engine", "ejs"); +app.set("views", path.join(__dirname, "views")); -app.use(express.static('public')); +app.use(express.static("public")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); const routes = require("./routes/routes.js"); -app.use('/', routes); +app.use("/", routes); app.use((req, res) => { - res.status(404).render('not_found'); + res.status(404).render("not_found"); +}); + +const startServer = async () => { + await connectToDb(); + const port = process.env.port || 3000; + app.listen(port, () => { + console.log(`Listening on http://localhost:${port} :-D`); }); +}; -const server = app.listen(3000, function () { - console.log("Listening on http://localhost:" + server.address().port, ":-D"); -}); \ No newline at end of file +startServer(); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..88cf458 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2722 @@ +{ + "name": "keyboard-shortcuts-practice", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/node": { + "version": "14.6.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.4.tgz", + "integrity": "sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "ajv": { + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", + "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "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", + "strip-ansi": "^5.1.0" + } + } + } + }, + "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 + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "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=" + }, + "aws4": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "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=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "optional": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "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==" + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "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 + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=" + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "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" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, + "dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ecstatic": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", + "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "requires": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", + "requires": { + "jake": "^10.6.1" + } + }, + "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 + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "filelist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", + "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "get-stream": { + "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" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "global-dirs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", + "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "dev": true, + "requires": { + "ini": "^1.3.5" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-server": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz", + "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==", + "requires": { + "colors": "1.0.3", + "corser": "~2.0.0", + "ecstatic": "^3.0.0", + "http-proxy": "^1.8.1", + "opener": "~1.4.0", + "optimist": "0.6.x", + "portfinder": "^1.0.13", + "union": "~0.4.3" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dev": true, + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + } + }, + "is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "optional": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jake": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "requires": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "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==" + }, + "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=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "moment": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz", + "integrity": "sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA==" + }, + "moment-timezone": { + "version": "0.5.31", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", + "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + } + }, + "needle": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", + "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "node-addon-api": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz", + "integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA==" + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "optional": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "optional": true, + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "optional": true + } + } + }, + "node-pre-gyp": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", + "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + }, + "dependencies": { + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } + }, + "nodemon": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz", + "integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==", + "dev": true, + "requires": { + "chokidar": "^3.2.2", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.2", + "update-notifier": "^4.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "opener": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", + "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=" + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + } + } + }, + "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=" + }, + "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-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", + "requires": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pg": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.3.3.tgz", + "integrity": "sha512-wmUyoQM/Xzmo62wgOdQAn5tl7u+IA1ZYK7qbuppi+3E+Gj4hlUxVHjInulieWrd0SfHi/ADriTb5ILJ/lsJrSg==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.3.0", + "pg-pool": "^3.2.1", + "pg-protocol": "^1.2.5", + "pg-types": "^2.1.0", + "pgpass": "1.x", + "semver": "4.3.2" + } + }, + "pg-connection-string": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.3.0.tgz", + "integrity": "sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w==" + }, + "pg-hstore": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.3.tgz", + "integrity": "sha512-qpeTpdkguFgfdoidtfeTho1Q1zPVPbtMHgs8eQ+Aan05iLmIs3Z3oo5DOZRclPGoQ4i68I1kCtQSJSa7i0ZVYg==", + "requires": { + "underscore": "^1.7.0" + } + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz", + "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA==" + }, + "pg-protocol": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.5.tgz", + "integrity": "sha512-1uYCckkuTfzz/FCefvavRywkowa6M5FohNMF5OjKrqo9PSR8gYc8poVmwwYQaBxhmQdBjhtP514eXy9/Us2xKg==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "requires": { + "split": "^1.0.0" + } + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "pump": { + "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" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "pupa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", + "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "registry-auth-token": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", + "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + } + } + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "requires": { + "any-promise": "^1.3.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "sequelize": { + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.5.tgz", + "integrity": "sha512-MiwiPkYSA8NWttRKAXdU9h0TxP6HAc1fl7qZmMO/VQqQOND83G4nZLXd0kWILtAoT9cxtZgFqeb/MPYgEeXwsw==", + "requires": { + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.26.0", + "moment-timezone": "^0.5.31", + "retry-as-promised": "^3.2.0", + "semver": "^7.3.2", + "sequelize-pool": "^6.0.0", + "toposort-class": "^1.0.1", + "uuid": "^8.1.0", + "validator": "^10.11.0", + "wkx": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + }, + "uuid": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==" + } + } + }, + "sequelize-pool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", + "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==" + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "requires": { + "through": "2" + } + }, + "sqlite3": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.0.tgz", + "integrity": "sha512-rjvqHFUaSGnzxDy2AHCwhHy6Zp6MNJzCPGYju4kD8yi6bze4d1/zMTg6C7JI49b7/EM7jKMTvyfN/4ylBKdwfw==", + "requires": { + "node-addon-api": "2.0.0", + "node-gyp": "3.x", + "node-pre-gyp": "^0.11.0" + } + }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "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" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "optional": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "term-size": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", + "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + } + }, + "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==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "undefsafe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", + "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", + "dev": true, + "requires": { + "debug": "^2.2.0" + } + }, + "underscore": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz", + "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==" + }, + "union": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", + "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", + "requires": { + "qs": "~2.3.3" + }, + "dependencies": { + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=" + } + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "update-notifier": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.1.tgz", + "integrity": "sha512-9y+Kds0+LoLG6yN802wVXoIfxYEwh3FlZwzMwpCZp62S2i1/Jzeqb9Eeeju3NSHccGGasfGlK5/vEHbAifYRDg==", + "dev": true, + "requires": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "requires": { + "punycode": "^2.1.0" + } + }, + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "optional": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, + "wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "requires": { + "@types/node": "*" + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + } + } +} diff --git a/package.json b/package.json index b021d2b..d3ba739 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,11 @@ "name": "keyboard-shortcuts-practice", "version": "1.0.0", "description": "[Techtonica](https://techtonica.org) is a nonprofit that provides free tech training with stipends and job placement to women and non-binary adults with low incomes.", - "main": "index.js", + "main": "app.js", "scripts": { - "start": "node app.js", - "dev": "nodemon -e js,ejs,json app.js", + "start": "npm run dev", + "start:prod": "NODE_ENV=production node app.js", + "dev": "NODE_ENV=development nodemon", "test": "mocha" }, "repository": { @@ -26,12 +27,19 @@ "morgan": "^1.9.1", "mysql": "^2.17.1", "path": "^0.12.7", - "pg": "^7.12.1", + "pg": "^8.3.3", "pg-hstore": "^2.3.3", "request": "^2.88.0", - "sequelize": "^5.19.2" + "sequelize": "^6.3.5", + "sqlite3": "^5.0.0" }, "devDependencies": { "nodemon": "^2.0.1" + }, + "nodemonConfig": { + "execMap": { + "watch": "js,ejs,json", + "js": "node --unhandled-rejections=strict" + } } } From d1c7d7cb7d8a3de3971cd081d27d11dfafb9194d Mon Sep 17 00:00:00 2001 From: Bill DePhillips <355438+vegetabill@users.noreply.github.com> Date: Sat, 12 Sep 2020 19:30:08 -0700 Subject: [PATCH 05/56] Fix port used in README and remove steps related to when the files were served by http-server (now using express) (#62) --- README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 47a1da3..2b1234b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # Keyboard Shortcuts Practice App + Try it out here: https://techtonica.github.io/keyboard-shortcuts-practice/ ![App Screenshot](/images/app-screenshot.png) ## Overview + [Techtonica](https://techtonica.org) is a nonprofit that provides free tech training with stipends and job placement to women and non-binary adults with low incomes. We discovered that our participants need an app similar to typing practice websites out there, but for Mac OS X keyboard shortcuts. @@ -17,18 +19,14 @@ can sign in, practice with the app, and save their progress. That way, the next 1. Run `npm install` to install all the packages. 1. Run `npm start` to start the server. -1. Navigate to `http://127.0.0.1:8080` in your browser. Your project should be running at this point. -1. If that's doesn't work, try `http://127.0.0.1:8080/index.html`, more details in the troubleshooting section below. -1. You should be good to go! - -## Troubleshooting - -If the browser shows ERR_INVALID_REDIRECT either add '/index.html' to the url ('http://127.0.0.1:8080/index.html') or downgrade your http-server version by running 'npm install -g http-server@0.9.0'. +1. Navigate to `http://localhost:3000` in your browser. Your project should be running at this point. ## Contributing / Volunteering + Go to [CONTRIBUTING.md](/CONTRIBUTING.md). ### Creative Commons Open-Source License + This work is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/legalcode). [![CC BY-SA 4.0](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)](https://creativecommons.org/licenses/by-sa/4.0/legalcode) From f7435d3a63cdb2a146921bbcf3e8e927eb45f0f3 Mon Sep 17 00:00:00 2001 From: Ambika Sadhu <34772783+ambikasadhu1101@users.noreply.github.com> Date: Thu, 1 Oct 2020 17:51:12 +0000 Subject: [PATCH 06/56] orm.js updated with model for UserAnswers --- JS/orm.js | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/JS/orm.js b/JS/orm.js index 26b47f1..a9bc87b 100644 --- a/JS/orm.js +++ b/JS/orm.js @@ -22,7 +22,38 @@ User.init( updatedAt: "updated_at", } ); - +class UserAnswers extends Model{} +UserAnswers.init( + { + id:{ + primaryKey : true, + type: Sequelize.INTEGER, + }, + user_id:{ + type: Sequelize.STRING, + allowNull: false + }, + question_number:{ + type: Sequelize.INTEGER, + allowNull: false + }, + is_correct:{ + type: Sequelize.BOOLEAN, + allowNull: false + }, + elapsed_time_ms:{ + type: Sequelize.INTEGER, + allowNull: false + }, + },{ + sequelize, + modelName: "user_answers", + createdAt: 'created_at', + updatedAt: false + } +); +User.hasOne(UserAnswers, {foreignKey: 'user_id'}); +UserAnswers.belongsTo(User,{foreignKey: 'user_id'}); const connectToDb = async () => { await sequelize.authenticate(); await sequelize.sync(); From 8cd549899c05d1aaf5974dc2b51dbaec01865f59 Mon Sep 17 00:00:00 2001 From: Ambika Sadhu <34772783+ambikasadhu1101@users.noreply.github.com> Date: Thu, 1 Oct 2020 18:35:47 +0000 Subject: [PATCH 07/56] updates to UserAnswers model --- JS/orm.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/JS/orm.js b/JS/orm.js index a9bc87b..784dabf 100644 --- a/JS/orm.js +++ b/JS/orm.js @@ -52,7 +52,7 @@ UserAnswers.init( updatedAt: false } ); -User.hasOne(UserAnswers, {foreignKey: 'user_id'}); +User.hasMany(UserAnswers, {foreignKey: 'user_id'}); UserAnswers.belongsTo(User,{foreignKey: 'user_id'}); const connectToDb = async () => { await sequelize.authenticate(); @@ -62,4 +62,5 @@ const connectToDb = async () => { module.exports = { User, connectToDb, + UserAnswers }; From 1a642f3ce4a136ec3b325beec781f4ab97b18935 Mon Sep 17 00:00:00 2001 From: ashley-g <69818337+ashley-g@users.noreply.github.com> Date: Thu, 1 Oct 2020 14:48:58 -0400 Subject: [PATCH 08/56] 34 caps lock toggle (#98) * fixed caps lock sync issue, capslock on is a keydown and capslock off is a keyup event * deleted unecesseray if condition in handle function for capslock --- public/scripts/main.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index ab91997..66448d1 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -95,11 +95,6 @@ function handle(e) { $("#"+e.key.toLowerCase()).toggleClass("pressed"); $('.letter').toggleClass('uppercase'); } - else if(e.key.toLowerCase()=="capslock" && caps==true) { - $("#"+e.key.toLowerCase()).toggleClass("pressed"); - $('.letter').toggleClass('uppercase'); - caps=false; - } else $("#"+e.key.toLowerCase() ).addClass("pressed"); } @@ -120,7 +115,11 @@ function release(e) { if(e.code.toLowerCase()=="space"){ $("#space").removeClass("pressed"); } - if(e.key.toLowerCase()=="capslock") return + if(e.key.toLowerCase()=="capslock"){ + $("#"+e.key.toLowerCase()).toggleClass("pressed"); + $('.letter').toggleClass('uppercase'); + caps=false; + } else{ $("#"+e.key.toLowerCase() ).removeClass("pressed"); } From 12b8ae0acd99ae57ec81dba48cf89ddd77d04b06 Mon Sep 17 00:00:00 2001 From: Alina L Date: Thu, 1 Oct 2020 12:48:46 -0700 Subject: [PATCH 09/56] docs: add step for PR description --- CONTRIBUTING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 88cfe81..956b9a9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,8 +26,9 @@ Prepare for contributing by following these beginner-friendly steps. 1. Read the description, and make sure to ask questions about anything that is unclear. 1. Start on your forked repo's `backend` branch with `git checkout backend`. 1. Make sure you have the latest version of the project with `git pull upstream backend` or `git merge upstream/backend`. -1. Create a new branch with `git checkout -b `. The name should include the issue number and the topic you're working in. For example, if its about adding a GET request, your command could be `git checkout -b add-get-request`. +1. Create a new branch with `git checkout -b `. The name should be short and describe the topic you're working in. For example, if its about adding a GET request for unser data, your command could be `git checkout -b add-user-get-request`. 1. Make and commit your changes on this new branch, and make a PR when you're ready. [Here are some directions on the process](http://www.dasblinkenlichten.com/how-to-create-a-github-pull-request-pr/). 1. When creating your PR, be sure to make your pull request to the `backend` feature branch: making a pull request to the backend branch 1. See your pull requests here: https://github.com/Techtonica/keyboard-shortcuts-practice/pulls +1. In your new PR's description, add `Fixes #`, for example `fixes #1`. This will automatically close the issue once your PR is merged, and it will link the issue with your PR. Also add a description of what the PR is, and how reviewers can validate it. From ebcc4fd2c13719d28e8270184bae062662eac8de Mon Sep 17 00:00:00 2001 From: Nadya Djojosantoso Date: Thu, 1 Oct 2020 13:06:15 -0700 Subject: [PATCH 10/56] Replace repetitive if blocks with lookup --- public/scripts/main.js | 46 +++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 66448d1..0297fae 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -17,6 +17,24 @@ const FIREFOX_RIGHT_COMMAND_STRING = 'OSRight'; const CHROME_LEFT_COMMAND_STRING = 'MetaLeft'; const CHROME_RIGHT_COMMAND_STRING = 'MetaRight'; +// Key names to ID +const keyToId = { + ctrl: 'control', + control: 'control', + command: 'metaleft', + cmd: 'metaleft', + meta: 'metaleft', + fn: 'fnc', + alt: 'optionleft', + shift: 'shiftleft', + esc: 'escape', + tab: 'tab', + 'space bar': 'space', + 'tilde(~)': 'tilde', + 'comma(,)': 'comma', + 'underscore(_)': 'minus' +}; + // this tracks when we started asking for the current key command let questionStartMS = 0; @@ -142,31 +160,9 @@ function promptKey2(key){ // Function to highlight any key passed as input function promptKey(key){ // Handling all key types - if(key.length==1) $("#"+key.toLowerCase()).toggleClass("prompt"); - else { - if(key.toLowerCase()=='ctrl'||key.toLowerCase()=='control') - $("#control").toggleClass("prompt"); - if(key.toLowerCase()=='command' || key.toLowerCase()=='cmd'|| key.toLowerCase()=="meta") - $("#metaleft").toggleClass("prompt"); - if(key.toLowerCase()=='fn') - $("#fnc").toggleClass("prompt"); - if(key.toLowerCase()=='alt') - $("#optionleft").toggleClass("prompt"); - if(key.toLowerCase()=='shift') - $("#shiftleft").toggleClass("prompt"); - if(key.toLowerCase()=='esc') - $("#escape").toggleClass("prompt"); - if(key.toLowerCase()=='space bar') - $("#space").toggleClass("prompt"); - if(key.toLowerCase()=='tab') - $("#tab").toggleClass("prompt"); - if(key.toLowerCase()=='tilde(~)') - $("#tilde").toggleClass("prompt"); - if(key.toLowerCase()=='comma(,)') - $("#comma").toggleClass("prompt"); - if(key.toLowerCase()=='underscore(_)') - $("#minus").toggleClass("prompt"); - } + key = key.toLowerCase(); + id = key.length == 1 ? key : keyToId[key]; + if (id) $('#' + id).toggleClass('prompt'); } // Function to read the next combination of keys and highlight it on keyboard From e3260866725e99e8b5eda40b19ddb7aa7715943b Mon Sep 17 00:00:00 2001 From: Sergio Moreno Baeza Date: Thu, 1 Oct 2020 23:16:20 +0200 Subject: [PATCH 11/56] Remove unneeded files (#107) --- shortcuts.txt | 34 ---------------------------------- userinfo.html | 12 ------------ 2 files changed, 46 deletions(-) delete mode 100644 shortcuts.txt delete mode 100644 userinfo.html diff --git a/shortcuts.txt b/shortcuts.txt deleted file mode 100644 index 064a264..0000000 --- a/shortcuts.txt +++ /dev/null @@ -1,34 +0,0 @@ -Ctrl-A How do you go to the beginning of the line you are currently typing on? -Ctrl-E How do you go to the end of the line you are currently typing on? -Ctrl-Q How do you clears everything on current line? -Ctrl-L How do you clear the screen using the control key? -Ctrl-K How do you cut everything forward to end of line? -Ctrl-U How do you cut everything backwards to beginning of line? -Ctrl-W How do you cut one word backwards using white space as delimiter? -Ctrl-Y How do you paste whatever was cut by the last cut command? -Command-X How do you cut the selected item and copy it to the clipboard? -Command-C How do you copy the selected item to the clipboard? -Command-V How do you paste the contents of the clipboard into the current document or app? -Command-Z How do you undo the previous command? -Command-Shift-Z How do you redo to reverse the undo command? -Command-A How do you select All items? -Command-F How do you find items in a document or open a Find window? -Command-G How do you find Again? (Find the next occurrence of the item previously found.) -Command-H How do you hide the windows of the front app? -Command-Option-H How do you view the front app but hide all other apps? -Command-K How do you clear the screen using the command key? -Command-M How do you minimize the front window to the Dock? -Command-Option-M How do you minimize all windows of the front app? -Command-N How do you open a new document or window? -Command-O How do you open the selected item, or open a dialog to select a file to open? -Command-P How do you print the current document? -Command-S How do you save the current document? -Command-W How do you close the front window? -Command-Option-W How do you close all windows of the app? -Command-Q How do you quit the app? -Option-Command-Esc How do you force quit? -Command–Space bar How do you show or hide the Spotlight search field? -Command-Tab How do you switch to the next most recently used app among your open apps? -Shift-Command-Tilde (~) How do you switch to the next most recently used window of the front app? -Shift-Command-3 How do you take a screenshot of the entire screen? -Command-Comma (,) How do you open preferences for the front app? diff --git a/userinfo.html b/userinfo.html deleted file mode 100644 index 4282c7d..0000000 --- a/userinfo.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - User Info - - -

hello

- -

after

- \ No newline at end of file From ae2c2ab57e8e5b6d02f6503da9da7e9d7fa973fb Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Thu, 1 Oct 2020 17:18:10 -0400 Subject: [PATCH 12/56] Added post endpoint to save an user answer --- JS/orm.js | 1 + JS/router.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/JS/orm.js b/JS/orm.js index 784dabf..7f40b5a 100644 --- a/JS/orm.js +++ b/JS/orm.js @@ -27,6 +27,7 @@ UserAnswers.init( { id:{ primaryKey : true, + autoIncrement: true, type: Sequelize.INTEGER, }, user_id:{ diff --git a/JS/router.js b/JS/router.js index c598d46..efd6259 100644 --- a/JS/router.js +++ b/JS/router.js @@ -1 +1 @@ -import { User } from 'orm.js'; \ No newline at end of file +import { User, UserAnswers } from 'orm.js'; \ No newline at end of file From 9c9d786e03aace8a00564ffa3c6674da304f297c Mon Sep 17 00:00:00 2001 From: David Stroud <31050943+dapper-gh@users.noreply.github.com> Date: Thu, 1 Oct 2020 17:46:16 -0400 Subject: [PATCH 13/56] refactor: Remove jQuery when possible (#109) --- package.json | 3 +- public/scripts/main.js | 172 ++++++++++++++++++++++++++--------------- 2 files changed, 112 insertions(+), 63 deletions(-) diff --git a/package.json b/package.json index d3ba739..0665c6e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "start": "npm run dev", "start:prod": "NODE_ENV=production node app.js", "dev": "NODE_ENV=development nodemon", - "test": "mocha" + "test": "mocha", + "dev:win": "nodemon" }, "repository": { "type": "git", diff --git a/public/scripts/main.js b/public/scripts/main.js index 0297fae..05e1315 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -1,9 +1,9 @@ // Global variable to keep track of CapsLock -var caps = false; -var allData ; -var reqKeys = [] -var typewriter; -var quesNo; +let caps = false; +let allData ; +let reqKeys = [] +let typewriter; +let quesNo; let pressed = new Set(); // event.keyCode Chrome and Firefox @@ -38,10 +38,46 @@ const keyToId = { // this tracks when we started asking for the current key command let questionStartMS = 0; -$(document).ready(function() { - //$("#retryButton").toggleClass("on"); +function setContainerHeight() { + let containerEls = document.getElementsByClassName("container"); + let height = document.body.scrollHeight; + for (let i = 0; i < containerEls.length; i++) { + containerEls[i].height = height; + } +} + +function toggleClass(el, className) { + if (!el) return; + let classes = el.className.split(" "); + let indexOfClass = classes.indexOf(className); + if (indexOfClass !== -1) classes.splice(indexOfClass, 1); + else classes.push(className); + el.className = classes.join(" "); +} + +function setClass(el, className, setTo) { + if (!el) return; + let classes = el.className.split(" "); + let indexOfClass = classes.indexOf(className); + if (indexOfClass !== -1) classes.splice(indexOfClass, 1); + if (setTo) classes.push(className); + el.className = classes.join(" "); +} + +function addClass(el, className) { + return setClass(el, className, true); +} + +function removeClass(el, className) { + return setClass(el, className, false); +} + +window.addEventListener("load", function() { + //toggleClass(document.getElementById(retryButton), "on"); //alert($('li[data-keycode="test"]').attr('id')); - $.getJSON( "scripts/shortcuts.json", function( data ) { + fetch( "scripts/shortcuts.json").then(function(r) { + return r.json(); + }).then(function( data ) { allData = data; if(localStorage.getItem("questionNo")==null){ localStorage.setItem("questionNo", "1"); @@ -49,14 +85,12 @@ $(document).ready(function() { } // Call readText() readText() - - updateTimingDisplay(); - }) - $('.container').css('height', $(window).height()); - $(window).on('resize', function() { - $('.container').css('height', $(window).height()); + updateTimingDisplay(); }); + + setContainerHeight(); + window.addEventListener("resize", setContainerHeight); }); function nextQuestion() { @@ -89,15 +123,15 @@ function prevQuestion() { // Function called on KeyDown to show Pressed key by adding class = 'pressed' function handle(e) { - var text1 = e.type + + let text1 = e.type + ' key=' + e.key + ' code=' + e.code if(e.code.toLowerCase()=="space"){ - $("#space").toggleClass("pressed"); + toggleClass(document.getElementById("space"), "pressed"); } if((e.which>=186 && e.which<=192)|| (e.which>=219 && e.which<=222)){ - $("#"+e.code.toLowerCase()).toggleClass("pressed"); + toggleClass(document.getElementById(e.code.toLowerCase()), "pressed"); } if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ let keyString = e.code; @@ -106,20 +140,23 @@ function handle(e) { } else if (e.code == FIREFOX_RIGHT_COMMAND_STRING) { keyString = CHROME_RIGHT_COMMAND_STRING } - $("#"+keyString.toLowerCase()).toggleClass("pressed"); + toggleClass(document.getElementById(keyString.toLowerCase()), "pressed"); } if(e.key.toLowerCase()=="capslock" && caps==false){ caps= true; - $("#"+e.key.toLowerCase()).toggleClass("pressed"); - $('.letter').toggleClass('uppercase'); + toggleClass(document.getElementById(e.key.toLowerCase()), "pressed"); + let letterEls = document.getElementsByClassName("letter"); + for (let i = 0; i < letterEls.length; i++) { + toggleClass(letterEls[i], "uppercase"); + } } - else $("#"+e.key.toLowerCase() ).addClass("pressed"); + else addClass(document.getElementById(e.key.toLowerCase()), "pressed"); } // Function called on KeyUp to reset the key by removing class = 'pressed' function release(e) { if((e.which>=186 && e.which<=192)|| (e.which>=219 && e.which<=222)){ - $("#"+e.code.toLowerCase()).removeClass("pressed"); + removeClass(document.getElementById(e.code.toLowerCase()), "pressed"); } if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ let keyString = e.code; @@ -128,32 +165,35 @@ function release(e) { } else if (e.code == FIREFOX_RIGHT_COMMAND_STRING) { keyString = CHROME_RIGHT_COMMAND_STRING } - $("#"+keyString.toLowerCase()).removeClass("pressed"); + removeClass(document.getElementById(keyString.toLowerCase()), "pressed"); } if(e.code.toLowerCase()=="space"){ - $("#space").removeClass("pressed"); + removeClass(document.getElementById("space"), "pressed"); } if(e.key.toLowerCase()=="capslock"){ - $("#"+e.key.toLowerCase()).toggleClass("pressed"); - $('.letter').toggleClass('uppercase'); + toggleClass(document.getElementById(e.key.toLowerCase()), "pressed"); + let letterEls = document.getElementsByClassName("letter"); + for (let i = 0; i < letterEls.length; i++) { + toggleClass(letterEls[i], "uppercase"); + } caps=false; - } + } else{ - $("#"+e.key.toLowerCase() ).removeClass("pressed"); + removeClass(document.getElementById(e.key.toLowerCase()), "pressed"); } } // May have to be removed. Not being used currently function highlightNextKey(params){ - $("#"+nxt.toLowerCase()).toggleClass("pressed"); - - + toggleClass(document.getElementById(nxt.toLowerCase()), "pressed"); + + } function promptKey2(key){ //if($('li[data-keycode="'+key+'"]'[0]).hasClass('prompt')){ - $($('li[data-keycode="'+key+'"]')[0]).toggleClass("prompt") + toggleClass(document.querySelector('li[data-keycode="'+key+'"]'), "prompt"); //} } @@ -162,7 +202,7 @@ function promptKey(key){ // Handling all key types key = key.toLowerCase(); id = key.length == 1 ? key : keyToId[key]; - if (id) $('#' + id).toggleClass('prompt'); + if (id) toggleClass(document.getElementById(id), 'prompt'); } // Function to read the next combination of keys and highlight it on keyboard @@ -173,17 +213,17 @@ function readText(){ answerkeys = allData[parseInt(quesNo)-1].keys //commandText = "A+Control" //$("#textdiv").text(); // Will be taken from some other list type of a source. //Each command will have an associated question text used in writeQuestion - var speed = 50 - var i = 0; + let speed = 50 + let i = 0; // Call writeQuestion to add question on the top textarea writeQuestion(allData[parseInt(localStorage.getItem("questionNo"))-1].question) - $.each(answerkeys , function(index, val) { + for (const val of answerkeys) { reqKeys.push(val) // Highlight the prompt keys promptKey2(val) - }); + } /* commandText.split('+').forEach(function(c) { if(c.toLowerCase()=="command"){ @@ -206,7 +246,7 @@ function readText(){ function writeQuestion(question) { if(typewriter!=null) { typewriter.state.eventQueue = []; - $('#textdiv span').first().text(''); + document.querySelector('#textdiv span').innerText = ""; } else { typewriter = new Typewriter(document.getElementById('textdiv'), { loop: false, @@ -220,57 +260,67 @@ function writeQuestion(question) { } function clearIncorrectIndication() { - $("#read").removeClass('incorrect'); + removeClass(document.getElementById(read), "incorrect"); }; function clearPromptKeys() { - $('.prompt').removeClass('prompt'); + let classEls = document.getElementsByClassName("prompt"); + for (let i = 0; i < classEls.length; i++) { + removeClass(classEls[i], "prompt"); + } }; function clearPressedKeys() { pressed.clear(); - $('.pressed').removeClass('pressed'); + let classEls = document.getElementsByClassName("pressed"); + for (let i = 0; i < classEls.length; i++) { + removeClass(classEls[i], "pressed"); + } }; function updateTimingDisplay() { - $('#timing-feedback').html(''); - var questionNo = localStorage.getItem('questionNo'); + document.getElementById('timing-feedback').innerHTML = ""; + let questionNo = localStorage.getItem('questionNo'); // grab the last bits of timing data - var timings = getHistory(questionNo).slice(-3); + let timings = getHistory(questionNo).slice(-3); // and then drop them into the boxes timings.forEach(function(t, idx) { - var element = $('#timing-' + idx); - element.html(t / 1000 + ' sec'); - element.show(); + let element = document.getElementById('timing-' + idx); + if (element) { + element.innerHTML = t / 1000 + ' sec'; + element.style.display = "initial"; + } }) // hide the boxes if we don't have timing data - for (var i = timings.length; i < 3; i++) { - $('#timing-' + i).hide(); + for (let i = timings.length; i < 3; i++) { + let el = document.getElementById('timing-' + i); + if (el) el.style.display = "hidden"; } } function onIncorrect() { - $('#textdiv').effect("shake", { distance: 3 }); - $("#read").addClass('incorrect'); + let el = document.getElementById("textdiv"); + //$('#textdiv').effect("shake", { distance: 3 }); // going to comment this because animations are a mess + addClass(document.getElementById("read"), "incorrect"); setTimeout(clearPressedKeys, 500); }; function handleTimingFeedback(questionNo, curMS) { - var previousTimings = getHistory(questionNo); + let previousTimings = getHistory(questionNo); if (previousTimings.length == 0) { return; } - var average = previousTimings.reduce( + let average = previousTimings.reduce( function(acc, cur) { return acc + cur }, 0, ) / previousTimings.length; - var delta = average - curMS; + let delta = average - curMS; - var template = null; + let template = null; if (delta > 0) { template = "
You were faster by ${delta} sec!"; } @@ -287,20 +337,20 @@ function handleTimingFeedback(questionNo, curMS) { // decimals if we actually need them, e.g., we want 1.5 not 1.50 // cf. https://stackoverflow.com/a/12830454 delta = +delta.toFixed(2); - $('#timing-feedback').html(template.replace('${delta}', delta)); + document.getElementById("timing-feedback").innerHTML = template.replace('${delta}', delta); } // Function to execute when correct keys are pressed. function onSuccess() { - var questionNo = localStorage.getItem("questionNo"); - var thisAnswerMS = Date.now() - questionStartMS; + let questionNo = localStorage.getItem("questionNo"); + let thisAnswerMS = Date.now() - questionStartMS; handleTimingFeedback(questionNo, thisAnswerMS); recordAnswer(questionNo, thisAnswerMS); saveHistory(); - $('#textdiv span').first().text('Correct Keys pressed!'); + document.querySelector('#textdiv span').innerText = 'Correct Keys pressed!'; clearPromptKeys(); clearPressedKeys(); - confetti($("#confetti").get(0), { spread: 180, startVelocity: 50, elementCount: 150 }); + confetti(document.getElementById("confetti"), { spread: 180, startVelocity: 50, elementCount: 150 }); setTimeout(nextQuestion, 1500); } @@ -372,5 +422,3 @@ window.addEventListener('focus', function (e) { onSuccess(); } }); - -sequelize.close(); From f42f2a4ea33c78150728be24c724833dfece2940 Mon Sep 17 00:00:00 2001 From: Aryan Verma Date: Fri, 2 Oct 2020 03:26:52 +0530 Subject: [PATCH 14/56] Replaced jQuery DOM Selectors with in-built one --- public/scripts/main.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 0297fae..25aaf76 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -113,13 +113,13 @@ function handle(e) { $("#"+e.key.toLowerCase()).toggleClass("pressed"); $('.letter').toggleClass('uppercase'); } - else $("#"+e.key.toLowerCase() ).addClass("pressed"); + else document.querySelector("#"+e.key.toLowerCase() ).classList.add("pressed"); } // Function called on KeyUp to reset the key by removing class = 'pressed' function release(e) { if((e.which>=186 && e.which<=192)|| (e.which>=219 && e.which<=222)){ - $("#"+e.code.toLowerCase()).removeClass("pressed"); + document.querySelector("#"+e.code.toLowerCase()).classList.remove("pressed"); } if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ let keyString = e.code; @@ -128,10 +128,10 @@ function release(e) { } else if (e.code == FIREFOX_RIGHT_COMMAND_STRING) { keyString = CHROME_RIGHT_COMMAND_STRING } - $("#"+keyString.toLowerCase()).removeClass("pressed"); + document.querySelector("#"+keyString.toLowerCase()).classList.remove("pressed"); } if(e.code.toLowerCase()=="space"){ - $("#space").removeClass("pressed"); + document.querySelector("#space").classList.remove("pressed"); } if(e.key.toLowerCase()=="capslock"){ $("#"+e.key.toLowerCase()).toggleClass("pressed"); @@ -139,7 +139,7 @@ function release(e) { caps=false; } else{ - $("#"+e.key.toLowerCase() ).removeClass("pressed"); + document.querySelector("#"+e.key.toLowerCase() ).classList.remove("pressed"); } } @@ -220,16 +220,16 @@ function writeQuestion(question) { } function clearIncorrectIndication() { - $("#read").removeClass('incorrect'); + document.querySelector("#read").classList.remove('incorrect'); }; function clearPromptKeys() { - $('.prompt').removeClass('prompt'); + document.querySelector('.prompt').classList.remove('prompt'); }; function clearPressedKeys() { pressed.clear(); - $('.pressed').removeClass('pressed'); + document.querySelector('.pressed').classList.remove('pressed'); }; function updateTimingDisplay() { @@ -253,7 +253,7 @@ function updateTimingDisplay() { function onIncorrect() { $('#textdiv').effect("shake", { distance: 3 }); - $("#read").addClass('incorrect'); + document.querySelector("#read").classList.add('incorrect'); setTimeout(clearPressedKeys, 500); }; From c60d9b3b8fb4ce819508bb854e95a60afddc8f48 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Thu, 1 Oct 2020 18:04:47 -0400 Subject: [PATCH 15/56] return res object in handlers --- routes/routes.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/routes/routes.js b/routes/routes.js index 76f17e7..683d649 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -1,6 +1,8 @@ const express = require('express'); const router = express.Router(); +const{ UserAnswers } = require('../JS/orm'); + router.get('/', (req, res) => { res.render('index'); }); @@ -9,4 +11,22 @@ router.get('/cheatsheet', (req,res) => { res.render('cheatsheet'); }) +router.post('/user/answers/question/:questionNumber', (req, res) => { + if(req.body.id) { + return res.status(400).json({'message': 'ID should not be provided'}); + } + UserAnswers.create({ + user_id: req.body.userId, + question_number: req.params.questionNumber, + is_correct: req.body.isCorrect, + elapsed_time_ms: req.body.elapsedTimeMs + }).then(userAnswer => { + return res.status(201).json(userAnswer) + }).catch(error => { + console.log(error); + return res.status(400).json(error.errors) + }) +}) + + module.exports = router; From 6cd49ef58583d986fedd82720367f3ea62809a6b Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Thu, 1 Oct 2020 18:05:20 -0400 Subject: [PATCH 16/56] added backend call when the answer is correct --- public/scripts/main.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 66448d1..7208e51 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -305,6 +305,7 @@ function onSuccess() { clearPromptKeys(); clearPressedKeys(); confetti($("#confetti").get(0), { spread: 180, startVelocity: 50, elementCount: 150 }); + createUserAnswer(questionNo, true, thisAnswerMS); setTimeout(nextQuestion, 1500); } @@ -377,4 +378,23 @@ window.addEventListener('focus', function (e) { } }); -sequelize.close(); +function createUserAnswer(questionNo, isCorrect, elapsedTimeMs){ + let requestBody = { + userId: 'guest', + isCorrect: isCorrect, + elapsedTimeMs: elapsedTimeMs + } + + fetch('http://localhost:3000/user/answers/question/' + questionNo, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(requestBody) + }).catch(error => { + // TODO: handle error messages in a better way + console.log(error); + }) +} + +//sequelize.close(); From 48b040ae7ba9df34f616cbeca11498338bc592d1 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Thu, 1 Oct 2020 18:23:32 -0400 Subject: [PATCH 17/56] solved merge conflict --- public/scripts/main.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 2fda3d6..a624e72 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -350,12 +350,8 @@ function onSuccess() { document.querySelector('#textdiv span').innerText = 'Correct Keys pressed!'; clearPromptKeys(); clearPressedKeys(); -<<<<<<< HEAD - confetti($("#confetti").get(0), { spread: 180, startVelocity: 50, elementCount: 150 }); - createUserAnswer(questionNo, true, thisAnswerMS); -======= confetti(document.getElementById("confetti"), { spread: 180, startVelocity: 50, elementCount: 150 }); ->>>>>>> 9c9d786e03aace8a00564ffa3c6674da304f297c + createUserAnswer(questionNo, true, thisAnswerMS); setTimeout(nextQuestion, 1500); } From 832a836387977765e733dcf7cdb31fc7ba21a211 Mon Sep 17 00:00:00 2001 From: racheltl <64662730+racheltl@users.noreply.github.com> Date: Thu, 1 Oct 2020 15:31:25 -0700 Subject: [PATCH 18/56] fix: Add defer to script elements for better loading experience (#113) --- views/index.ejs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/views/index.ejs b/views/index.ejs index f15a859..8644711 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -8,12 +8,12 @@ - - - - - - + + + + + +
From d26f2ff2a71a1eb55cd4a62d73c2536f4769a5ab Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Thu, 1 Oct 2020 18:40:40 -0400 Subject: [PATCH 19/56] fixed mistake with site url --- public/scripts/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index a624e72..8429e6c 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -430,8 +430,8 @@ function createUserAnswer(questionNo, isCorrect, elapsedTimeMs){ isCorrect: isCorrect, elapsedTimeMs: elapsedTimeMs } - - fetch('http://localhost:3000/user/answers/question/' + questionNo, { + + fetch(document.URL + 'user/answers/question/' + questionNo, { method: 'POST', headers: { 'Content-Type': 'application/json' From 001c5b22c6d8b8a5820e0726718372a3c5137da4 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Thu, 1 Oct 2020 19:20:44 -0400 Subject: [PATCH 20/56] added find by user_id validation --- routes/routes.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/routes/routes.js b/routes/routes.js index 683d649..b133d8c 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -1,7 +1,7 @@ const express = require('express'); const router = express.Router(); -const{ UserAnswers } = require('../JS/orm'); +const{ User, UserAnswers } = require('../JS/orm'); router.get('/', (req, res) => { res.render('index'); @@ -15,13 +15,23 @@ router.post('/user/answers/question/:questionNumber', (req, res) => { if(req.body.id) { return res.status(400).json({'message': 'ID should not be provided'}); } - UserAnswers.create({ - user_id: req.body.userId, - question_number: req.params.questionNumber, - is_correct: req.body.isCorrect, - elapsed_time_ms: req.body.elapsedTimeMs - }).then(userAnswer => { - return res.status(201).json(userAnswer) + // Created won't be needed when issue #74 has been solved, should be changed by findOne and handle the errors + User.findOrCreate({ + where: {id: req.body.userId} + }).then(users => { + let user = users[0]; + + UserAnswers.create({ + user_id: user.id, + question_number: req.params.questionNumber, + is_correct: req.body.isCorrect, + elapsed_time_ms: req.body.elapsedTimeMs + }).then(userAnswer => { + return res.status(201).json(userAnswer) + }).catch(error => { + console.log(error); + return res.status(400).json(error.errors) + }) }).catch(error => { console.log(error); return res.status(400).json(error.errors) From 48ebbc5b767aec0e89ba61dc3363df787a3c7d05 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Thu, 1 Oct 2020 19:21:21 -0400 Subject: [PATCH 21/56] deleted autoincrement config on UserAnswers model --- JS/orm.js | 1 - 1 file changed, 1 deletion(-) diff --git a/JS/orm.js b/JS/orm.js index 7f40b5a..784dabf 100644 --- a/JS/orm.js +++ b/JS/orm.js @@ -27,7 +27,6 @@ UserAnswers.init( { id:{ primaryKey : true, - autoIncrement: true, type: Sequelize.INTEGER, }, user_id:{ From bd631e2a55ccec1ee03ce0ffed8e173b0256d0eb Mon Sep 17 00:00:00 2001 From: Izzy Berzsenyi Date: Thu, 1 Oct 2020 18:37:18 -0500 Subject: [PATCH 22/56] installing express-openid-connecyt --- package-lock.json | 444 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 2 files changed, 436 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 88cf458..7c78613 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,54 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@hapi/address": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-4.1.0.tgz", + "integrity": "sha512-SkszZf13HVgGmChdHo/PxchnSaCJ6cetVqLzyciudzZRT0jcOouIF/Q93mgjw8cce+D+4F4C1Z/WrfFN+O3VHQ==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@hapi/formula": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-2.0.0.tgz", + "integrity": "sha512-V87P8fv7PI0LH7LiVi8Lkf3x+KCO7pQozXRssAHNXXL9L1K+uyu4XypLXwxqVDKgyQai6qj3/KteNlrqDx4W5A==" + }, + "@hapi/hoek": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.1.0.tgz", + "integrity": "sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw==" + }, + "@hapi/joi": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-17.1.1.tgz", + "integrity": "sha512-p4DKeZAoeZW4g3u7ZeRo+vCDuSDgSvtsB/NpfjXEHTUjSeINAi/RrVOWiVQ1isaoLzMvFEhe8n5065mQq1AdQg==", + "requires": { + "@hapi/address": "^4.0.1", + "@hapi/formula": "^2.0.0", + "@hapi/hoek": "^9.0.0", + "@hapi/pinpoint": "^2.0.0", + "@hapi/topo": "^5.0.0" + } + }, + "@hapi/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-vzXR5MY7n4XeIvLpfl3HtE3coZYO4raKXW766R6DZw/6aLqR26iuZ109K7a0NtF2Db0jxqh7xz2AxkUwpUFybw==" + }, + "@hapi/topo": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.0.0.tgz", + "integrity": "sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -19,17 +67,49 @@ "defer-to-connect": "^1.0.1" } }, + "@types/cacheable-request": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz", + "integrity": "sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==", + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/http-cache-semantics": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", + "integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==" + }, + "@types/keyv": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz", + "integrity": "sha512-MPtoySlAZQ37VoLaPcTHCu1RWJ4llDkULYZIzOYxlhxBqYPB0RsRlmMU0R6tahtFe27mIdkHV+551ZWV4PLmVw==", + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "14.6.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.4.tgz", "integrity": "sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==" }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "requires": { + "@types/node": "*" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -44,6 +124,15 @@ "negotiator": "0.6.2" } }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.12.4", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", @@ -163,6 +252,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "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", @@ -312,6 +406,11 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "cacheable-lookup": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.3.tgz", + "integrity": "sha512-W+JBqF9SWe18A72XFzN/V/CULFzPm7sBXzzR6ekkE+3tLG72wFZrBiBZhrZuDoYexop4PHJVdFAKb/Nj9+tm9w==" + }, "cacheable-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", @@ -355,6 +454,11 @@ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "cb": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cb/-/cb-0.1.0.tgz", + "integrity": "sha1-JvfnQPKAj6zIPO97IDkuTYgbUgM=" + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -392,17 +496,26 @@ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, "cli-boxes": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, "requires": { "mimic-response": "^1.0.0" } @@ -635,7 +748,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -703,6 +815,72 @@ "vary": "~1.1.2" } }, + "express-openid-connect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/express-openid-connect/-/express-openid-connect-2.0.0.tgz", + "integrity": "sha512-xMpAHUT5/Fe2SBV1c8t/lW0uXgPT8T5E49r9RUQsRpYCicRG6bViI+xDBJ6o7L7IQCqSnpmBOvxbzAPWNvFg7w==", + "requires": { + "@hapi/joi": "^17.1.1", + "cb": "^0.1.0", + "clone": "^2.1.2", + "cookie": "^0.4.1", + "debug": "^4.1.1", + "futoin-hkdf": "^1.3.2", + "http-errors": "^1.7.3", + "jose": "^2.0.0", + "on-headers": "^1.0.2", + "openid-client": "^4.0.0", + "p-memoize": "^4.0.0", + "url-join": "^4.0.1" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "http-errors": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -816,6 +994,11 @@ "rimraf": "2" } }, + "futoin-hkdf": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.3.2.tgz", + "integrity": "sha512-3EVi3ETTyJg5PSXlxLCaUVVn0pSbDf62L3Gwxne7Uq+d8adOSNWQAad4gg7WToHkcgnCJb3Wlb1P8r4Evj4GPw==" + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -974,8 +1157,7 @@ "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, "http-errors": { "version": "1.7.2", @@ -1024,6 +1206,15 @@ "sshpk": "^1.7.0" } }, + "http2-wrapper": { + "version": "1.0.0-beta.5.2", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz", + "integrity": "sha512-xYz9goEyBnC8XwXDTuC/MZ6t+MrKVQZOk4s7+PaDkwIsQd8IwqvM+0M6bA/2lvG8GHXcPdf+MejTUeO2LCPCeQ==", + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1058,6 +1249,11 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, "inflection": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", @@ -1197,6 +1393,14 @@ "minimatch": "^3.0.4" } }, + "jose": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.2.tgz", + "integrity": "sha512-yD93lsiMA1go/qxSY/vXWBodmIZJIxeB7QhFi8z1yQ3KUwKENqI9UA8VCHlQ5h3x1zWuWZjoY87ByQzkQbIrQg==", + "requires": { + "@panva/asn1.js": "^1.0.0" + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -1263,6 +1467,14 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -1280,11 +1492,33 @@ } } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "requires": { + "p-defer": "^1.0.0" + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, + "mem": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-6.1.1.tgz", + "integrity": "sha512-Ci6bIfq/UgcxPTYa8dQQ5FY3BzKkT894bwXWXxC/zqs0XgMO2cT20CGkOqda7gZNkmK5VP4x89IGZ6K7hfbn3Q==", + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.0.0" + } + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -1313,11 +1547,15 @@ "mime-db": "1.44.0" } }, + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==" + }, "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" }, "minimatch": { "version": "3.0.4", @@ -1595,8 +1833,7 @@ "normalize-url": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", - "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", - "dev": true + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" }, "npm-bundled": { "version": "1.1.1", @@ -1647,6 +1884,16 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "object-hash": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz", + "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==" + }, + "oidc-token-hash": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.0.tgz", + "integrity": "sha512-8Yr4CZSv+Tn8ZkN3iN2i2w2G92mUKClp4z7EGUfdsERiYSbj7P4i/NHm72ft+aUdsiFx9UdIPSTwbyzQ6C4URg==" + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -1673,6 +1920,125 @@ "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=" }, + "openid-client": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-4.1.1.tgz", + "integrity": "sha512-/qch3I3v8UtO0A7wVgyXJJjGX/knR8bv06DQpLuKQqLG5u4AHcgusGuVKPKAcneLZvHKbKovF2+3e2ngXyuudA==", + "requires": { + "base64url": "^3.0.1", + "got": "^11.6.2", + "jose": "^2.0.2", + "lru-cache": "^6.0.0", + "make-error": "^1.3.6", + "object-hash": "^2.0.1", + "oidc-token-hash": "^5.0.0", + "p-any": "^3.0.0" + }, + "dependencies": { + "@sindresorhus/is": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-3.1.2.tgz", + "integrity": "sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ==" + }, + "@szmarczak/http-timer": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "cacheable-request": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", + "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^2.0.0" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "defer-to-connect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz", + "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==" + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/got/-/got-11.7.0.tgz", + "integrity": "sha512-7en2XwH2MEqOsrK0xaKhbWibBoZqy+f1RSUoIeF1BLcnf+pyQdDsljWMfmOh+QKJwuvDIiKx38GtPh5wFdGGjg==", + "requires": { + "@sindresorhus/is": "^3.1.1", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "keyv": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", + "requires": { + "json-buffer": "3.0.1" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "p-cancelable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" + }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "requires": { + "lowercase-keys": "^2.0.0" + } + } + } + }, "optimist": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", @@ -1708,12 +2074,58 @@ "os-tmpdir": "^1.0.0" } }, + "p-any": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-any/-/p-any-3.0.0.tgz", + "integrity": "sha512-5rqbqfsRWNb0sukt0awwgJMlaep+8jV45S15SKKB34z4UuzjcofIfnriCBhWjZP2jbVtjt9yRl7buB6RlKsu9w==", + "requires": { + "p-cancelable": "^2.0.0", + "p-some": "^5.0.0" + }, + "dependencies": { + "p-cancelable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" + } + } + }, "p-cancelable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-memoize": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/p-memoize/-/p-memoize-4.0.1.tgz", + "integrity": "sha512-km0sP12uE0dOZ5qP+s7kGVf07QngxyG0gS8sYFvFWhqlgzOsSy+m71aUejf/0akxj5W7gE//2G74qTv6b4iMog==", + "requires": { + "mem": "^6.0.1", + "mimic-fn": "^3.0.0" + } + }, + "p-some": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-some/-/p-some-5.0.0.tgz", + "integrity": "sha512-Js5XZxo6vHjB9NOYAzWDYAIyyiPvva0DWESAIWIK7uhSpGsyg5FwUPxipU/SOQx5x9EqhOh545d1jo6cVkitig==", + "requires": { + "aggregate-error": "^3.0.0", + "p-cancelable": "^2.0.0" + }, + "dependencies": { + "p-cancelable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" + } + } + }, "package-json": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", @@ -1933,7 +2345,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" @@ -1958,6 +2369,11 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2065,6 +2481,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, + "resolve-alpn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.0.0.tgz", + "integrity": "sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA==" + }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -2717,6 +3138,11 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index d3ba739..6567b99 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "ejs": "^3.0.1", "express": "^4.17.1", "http-server": "^0.11.1", + "express-openid-connect": "^2.0.0", "morgan": "^1.9.1", "mysql": "^2.17.1", "path": "^0.12.7", From 33a1a0eea6ee38d4d24ce0aea487fa0a616a7c98 Mon Sep 17 00:00:00 2001 From: Izzy Berzsenyi Date: Thu, 1 Oct 2020 18:37:40 -0500 Subject: [PATCH 23/56] updating the README with instructions for Auth0 --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 2b1234b..b77d313 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,12 @@ This project should train and test users to use the quicker keyboard shortcuts i Our goal for the backend project is to create a persistent app where users can sign in, practice with the app, and save their progress. That way, the next time they sign in, they can pick up where they left off rather than starting at the beginning. +# Setting up Auth0 and creating an account +1. Create a [free personal Auth0 account](https://auth0.com/) +1. Create a `Regular Web Application` +1. Run `mv .env.example .env` to create a .env file +1. From the settings page of your Auth0 web application fill in the environment variables, ensuring that the `AUTH0_ISSUER_BASE_URL` is the Domain URL starting with `https://` + ## Running the project 1. Run `npm install` to install all the packages. From 79a8cea04e4d594aeef4bd7044baa8c2db5c31b4 Mon Sep 17 00:00:00 2001 From: Izzy Berzsenyi Date: Thu, 1 Oct 2020 18:38:11 -0500 Subject: [PATCH 24/56] integrating Auth0 middleware into server --- .env.example | 3 +++ JS/auth0.js | 33 +++++++++++++++++++++++++++++++++ app.js | 6 ++++++ 3 files changed, 42 insertions(+) create mode 100644 JS/auth0.js diff --git a/.env.example b/.env.example index 8bf93a9..68c1f29 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,4 @@ DB_URL=dev mode defaults to sqlite (so this is not needed) +AUTH0_CLIENT_ID=YOUR_CLIENT_ID +AUTH0_SECRET=YOU_CLIENT_SECRET +AUTH0_ISSUER_BASE_URL=APPLICATION_TENANT_DOMAIN_URL diff --git a/JS/auth0.js b/JS/auth0.js new file mode 100644 index 0000000..c59eb99 --- /dev/null +++ b/JS/auth0.js @@ -0,0 +1,33 @@ +const { AUTH0_SECRET, AUTH0_CLIENT_ID, AUTH0_ISSUER_BASE_URL } = process.env; +const port = process.env.port || 3000; +let auth_config = undefined; + +const secretGiven = () => AUTH0_SECRET != undefined; +const idGiven = () => AUTH0_CLIENT_ID != undefined; +const isValidUrl = () => { + try { + new URL(AUTH0_ISSUER_BASE_URL); + } catch (_) { + return false; + } + if (string.startsWith("https://")) { + return true + } else { + throw new Error("Auth0 issuer base url is not valid, must begin with 'https://'"); + } +} + +if (secretGiven && idGiven && isValidUrl) { + auth_config = { + authRequired: false, + auth0Logout: true, + issuerBaseURL: AUTH0_ISSUER_BASE_URL, + baseURL: 'http://localhost:'.concat(port), + clientID: AUTH0_CLIENT_ID, + secret: AUTH0_SECRET, + }; +} + +module.exports = { + auth_config +}; diff --git a/app.js b/app.js index 371eda2..ca1b76f 100644 --- a/app.js +++ b/app.js @@ -2,7 +2,9 @@ const path = require("path"); const morgan = require("morgan"); const express = require("express"); const bodyParser = require("body-parser"); +const { auth } = require('express-openid-connect'); const { connectToDb } = require("./JS/orm"); +const { auth_config } = require("./JS/auth0"); const app = express(); app.use(morgan("dev")); //morgan gives us useful logging @@ -15,6 +17,10 @@ app.use(express.static("public")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); +if (auth_config != undefined) { + app.use(auth(auth_config)); // auth router attaches /login, /logout, and /callback routes to the baseURL +} + const routes = require("./routes/routes.js"); app.use("/", routes); From 39ccc612743271d36c1e0d0aa0fe8accef091aa7 Mon Sep 17 00:00:00 2001 From: Alina L Date: Thu, 1 Oct 2020 16:46:53 -0700 Subject: [PATCH 25/56] Revert "refactor: Remove jQuery when possible (#109)" This reverts commit 9c9d786e03aace8a00564ffa3c6674da304f297c. --- package.json | 3 +- public/scripts/main.js | 172 +++++++++++++++-------------------------- 2 files changed, 63 insertions(+), 112 deletions(-) diff --git a/package.json b/package.json index 0665c6e..d3ba739 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,7 @@ "start": "npm run dev", "start:prod": "NODE_ENV=production node app.js", "dev": "NODE_ENV=development nodemon", - "test": "mocha", - "dev:win": "nodemon" + "test": "mocha" }, "repository": { "type": "git", diff --git a/public/scripts/main.js b/public/scripts/main.js index 05e1315..0297fae 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -1,9 +1,9 @@ // Global variable to keep track of CapsLock -let caps = false; -let allData ; -let reqKeys = [] -let typewriter; -let quesNo; +var caps = false; +var allData ; +var reqKeys = [] +var typewriter; +var quesNo; let pressed = new Set(); // event.keyCode Chrome and Firefox @@ -38,46 +38,10 @@ const keyToId = { // this tracks when we started asking for the current key command let questionStartMS = 0; -function setContainerHeight() { - let containerEls = document.getElementsByClassName("container"); - let height = document.body.scrollHeight; - for (let i = 0; i < containerEls.length; i++) { - containerEls[i].height = height; - } -} - -function toggleClass(el, className) { - if (!el) return; - let classes = el.className.split(" "); - let indexOfClass = classes.indexOf(className); - if (indexOfClass !== -1) classes.splice(indexOfClass, 1); - else classes.push(className); - el.className = classes.join(" "); -} - -function setClass(el, className, setTo) { - if (!el) return; - let classes = el.className.split(" "); - let indexOfClass = classes.indexOf(className); - if (indexOfClass !== -1) classes.splice(indexOfClass, 1); - if (setTo) classes.push(className); - el.className = classes.join(" "); -} - -function addClass(el, className) { - return setClass(el, className, true); -} - -function removeClass(el, className) { - return setClass(el, className, false); -} - -window.addEventListener("load", function() { - //toggleClass(document.getElementById(retryButton), "on"); +$(document).ready(function() { + //$("#retryButton").toggleClass("on"); //alert($('li[data-keycode="test"]').attr('id')); - fetch( "scripts/shortcuts.json").then(function(r) { - return r.json(); - }).then(function( data ) { + $.getJSON( "scripts/shortcuts.json", function( data ) { allData = data; if(localStorage.getItem("questionNo")==null){ localStorage.setItem("questionNo", "1"); @@ -85,12 +49,14 @@ window.addEventListener("load", function() { } // Call readText() readText() - + updateTimingDisplay(); - }); + }) - setContainerHeight(); - window.addEventListener("resize", setContainerHeight); + $('.container').css('height', $(window).height()); + $(window).on('resize', function() { + $('.container').css('height', $(window).height()); + }); }); function nextQuestion() { @@ -123,15 +89,15 @@ function prevQuestion() { // Function called on KeyDown to show Pressed key by adding class = 'pressed' function handle(e) { - let text1 = e.type + + var text1 = e.type + ' key=' + e.key + ' code=' + e.code if(e.code.toLowerCase()=="space"){ - toggleClass(document.getElementById("space"), "pressed"); + $("#space").toggleClass("pressed"); } if((e.which>=186 && e.which<=192)|| (e.which>=219 && e.which<=222)){ - toggleClass(document.getElementById(e.code.toLowerCase()), "pressed"); + $("#"+e.code.toLowerCase()).toggleClass("pressed"); } if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ let keyString = e.code; @@ -140,23 +106,20 @@ function handle(e) { } else if (e.code == FIREFOX_RIGHT_COMMAND_STRING) { keyString = CHROME_RIGHT_COMMAND_STRING } - toggleClass(document.getElementById(keyString.toLowerCase()), "pressed"); + $("#"+keyString.toLowerCase()).toggleClass("pressed"); } if(e.key.toLowerCase()=="capslock" && caps==false){ caps= true; - toggleClass(document.getElementById(e.key.toLowerCase()), "pressed"); - let letterEls = document.getElementsByClassName("letter"); - for (let i = 0; i < letterEls.length; i++) { - toggleClass(letterEls[i], "uppercase"); - } + $("#"+e.key.toLowerCase()).toggleClass("pressed"); + $('.letter').toggleClass('uppercase'); } - else addClass(document.getElementById(e.key.toLowerCase()), "pressed"); + else $("#"+e.key.toLowerCase() ).addClass("pressed"); } // Function called on KeyUp to reset the key by removing class = 'pressed' function release(e) { if((e.which>=186 && e.which<=192)|| (e.which>=219 && e.which<=222)){ - removeClass(document.getElementById(e.code.toLowerCase()), "pressed"); + $("#"+e.code.toLowerCase()).removeClass("pressed"); } if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ let keyString = e.code; @@ -165,35 +128,32 @@ function release(e) { } else if (e.code == FIREFOX_RIGHT_COMMAND_STRING) { keyString = CHROME_RIGHT_COMMAND_STRING } - removeClass(document.getElementById(keyString.toLowerCase()), "pressed"); + $("#"+keyString.toLowerCase()).removeClass("pressed"); } if(e.code.toLowerCase()=="space"){ - removeClass(document.getElementById("space"), "pressed"); + $("#space").removeClass("pressed"); } if(e.key.toLowerCase()=="capslock"){ - toggleClass(document.getElementById(e.key.toLowerCase()), "pressed"); - let letterEls = document.getElementsByClassName("letter"); - for (let i = 0; i < letterEls.length; i++) { - toggleClass(letterEls[i], "uppercase"); - } + $("#"+e.key.toLowerCase()).toggleClass("pressed"); + $('.letter').toggleClass('uppercase'); caps=false; - } + } else{ - removeClass(document.getElementById(e.key.toLowerCase()), "pressed"); + $("#"+e.key.toLowerCase() ).removeClass("pressed"); } } // May have to be removed. Not being used currently function highlightNextKey(params){ - toggleClass(document.getElementById(nxt.toLowerCase()), "pressed"); - - + $("#"+nxt.toLowerCase()).toggleClass("pressed"); + + } function promptKey2(key){ //if($('li[data-keycode="'+key+'"]'[0]).hasClass('prompt')){ - toggleClass(document.querySelector('li[data-keycode="'+key+'"]'), "prompt"); + $($('li[data-keycode="'+key+'"]')[0]).toggleClass("prompt") //} } @@ -202,7 +162,7 @@ function promptKey(key){ // Handling all key types key = key.toLowerCase(); id = key.length == 1 ? key : keyToId[key]; - if (id) toggleClass(document.getElementById(id), 'prompt'); + if (id) $('#' + id).toggleClass('prompt'); } // Function to read the next combination of keys and highlight it on keyboard @@ -213,17 +173,17 @@ function readText(){ answerkeys = allData[parseInt(quesNo)-1].keys //commandText = "A+Control" //$("#textdiv").text(); // Will be taken from some other list type of a source. //Each command will have an associated question text used in writeQuestion - let speed = 50 - let i = 0; + var speed = 50 + var i = 0; // Call writeQuestion to add question on the top textarea writeQuestion(allData[parseInt(localStorage.getItem("questionNo"))-1].question) - for (const val of answerkeys) { + $.each(answerkeys , function(index, val) { reqKeys.push(val) // Highlight the prompt keys promptKey2(val) - } + }); /* commandText.split('+').forEach(function(c) { if(c.toLowerCase()=="command"){ @@ -246,7 +206,7 @@ function readText(){ function writeQuestion(question) { if(typewriter!=null) { typewriter.state.eventQueue = []; - document.querySelector('#textdiv span').innerText = ""; + $('#textdiv span').first().text(''); } else { typewriter = new Typewriter(document.getElementById('textdiv'), { loop: false, @@ -260,67 +220,57 @@ function writeQuestion(question) { } function clearIncorrectIndication() { - removeClass(document.getElementById(read), "incorrect"); + $("#read").removeClass('incorrect'); }; function clearPromptKeys() { - let classEls = document.getElementsByClassName("prompt"); - for (let i = 0; i < classEls.length; i++) { - removeClass(classEls[i], "prompt"); - } + $('.prompt').removeClass('prompt'); }; function clearPressedKeys() { pressed.clear(); - let classEls = document.getElementsByClassName("pressed"); - for (let i = 0; i < classEls.length; i++) { - removeClass(classEls[i], "pressed"); - } + $('.pressed').removeClass('pressed'); }; function updateTimingDisplay() { - document.getElementById('timing-feedback').innerHTML = ""; - let questionNo = localStorage.getItem('questionNo'); + $('#timing-feedback').html(''); + var questionNo = localStorage.getItem('questionNo'); // grab the last bits of timing data - let timings = getHistory(questionNo).slice(-3); + var timings = getHistory(questionNo).slice(-3); // and then drop them into the boxes timings.forEach(function(t, idx) { - let element = document.getElementById('timing-' + idx); - if (element) { - element.innerHTML = t / 1000 + ' sec'; - element.style.display = "initial"; - } + var element = $('#timing-' + idx); + element.html(t / 1000 + ' sec'); + element.show(); }) // hide the boxes if we don't have timing data - for (let i = timings.length; i < 3; i++) { - let el = document.getElementById('timing-' + i); - if (el) el.style.display = "hidden"; + for (var i = timings.length; i < 3; i++) { + $('#timing-' + i).hide(); } } function onIncorrect() { - let el = document.getElementById("textdiv"); - //$('#textdiv').effect("shake", { distance: 3 }); // going to comment this because animations are a mess - addClass(document.getElementById("read"), "incorrect"); + $('#textdiv').effect("shake", { distance: 3 }); + $("#read").addClass('incorrect'); setTimeout(clearPressedKeys, 500); }; function handleTimingFeedback(questionNo, curMS) { - let previousTimings = getHistory(questionNo); + var previousTimings = getHistory(questionNo); if (previousTimings.length == 0) { return; } - let average = previousTimings.reduce( + var average = previousTimings.reduce( function(acc, cur) { return acc + cur }, 0, ) / previousTimings.length; - let delta = average - curMS; + var delta = average - curMS; - let template = null; + var template = null; if (delta > 0) { template = "
You were faster by ${delta} sec!"; } @@ -337,20 +287,20 @@ function handleTimingFeedback(questionNo, curMS) { // decimals if we actually need them, e.g., we want 1.5 not 1.50 // cf. https://stackoverflow.com/a/12830454 delta = +delta.toFixed(2); - document.getElementById("timing-feedback").innerHTML = template.replace('${delta}', delta); + $('#timing-feedback').html(template.replace('${delta}', delta)); } // Function to execute when correct keys are pressed. function onSuccess() { - let questionNo = localStorage.getItem("questionNo"); - let thisAnswerMS = Date.now() - questionStartMS; + var questionNo = localStorage.getItem("questionNo"); + var thisAnswerMS = Date.now() - questionStartMS; handleTimingFeedback(questionNo, thisAnswerMS); recordAnswer(questionNo, thisAnswerMS); saveHistory(); - document.querySelector('#textdiv span').innerText = 'Correct Keys pressed!'; + $('#textdiv span').first().text('Correct Keys pressed!'); clearPromptKeys(); clearPressedKeys(); - confetti(document.getElementById("confetti"), { spread: 180, startVelocity: 50, elementCount: 150 }); + confetti($("#confetti").get(0), { spread: 180, startVelocity: 50, elementCount: 150 }); setTimeout(nextQuestion, 1500); } @@ -422,3 +372,5 @@ window.addEventListener('focus', function (e) { onSuccess(); } }); + +sequelize.close(); From fd97006ec16a5366b54e0fe9f5cad764863d0946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=C3=BAl=20D=C3=ADaz=20Navarrete?= Date: Thu, 1 Oct 2020 18:50:01 -0500 Subject: [PATCH 26/56] Add cross-env package for processing env variables in any platform (#112) Co-authored-by: Paul Diaz Navarrete --- package-lock.json | 55 +++++++++++++++++++++++++++++++++++++++++++++-- package.json | 10 ++++----- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 88cf458..832981a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -495,6 +495,37 @@ "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=" }, + "cross-env": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz", + "integrity": "sha512-KZP/bMEOJEDCkDQAyRhu3RL2ZO/SUVrxQVI0G3YEQ+OLbRA3c6zgixe8Mq8a/z7+HKlNEjo8oiLUs8iRijY2Rw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -1178,8 +1209,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "optional": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isstream": { "version": "0.1.2", @@ -1758,6 +1788,12 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -2225,6 +2261,21 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", diff --git a/package.json b/package.json index 0665c6e..33d0008 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,10 @@ "description": "[Techtonica](https://techtonica.org) is a nonprofit that provides free tech training with stipends and job placement to women and non-binary adults with low incomes.", "main": "app.js", "scripts": { - "start": "npm run dev", - "start:prod": "NODE_ENV=production node app.js", - "dev": "NODE_ENV=development nodemon", - "test": "mocha", - "dev:win": "nodemon" + "start": "cross-env npm run dev", + "start:prod": "cross-env NODE_ENV=production node app.js", + "dev": "cross-env NODE_ENV=development nodemon", + "test": "mocha" }, "repository": { "type": "git", @@ -35,6 +34,7 @@ "sqlite3": "^5.0.0" }, "devDependencies": { + "cross-env": "^7.0.2", "nodemon": "^2.0.1" }, "nodemonConfig": { From 21c1043d8e7275c151a6bb5d742987a3844b5f2e Mon Sep 17 00:00:00 2001 From: Astha Upadhyay <01astha@gmail.com> Date: Fri, 2 Oct 2020 05:24:09 +0530 Subject: [PATCH 27/56] Replacing Jquery with Fetch in main.js(#114) --- public/scripts/main.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 59cfacf..53a5312 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -41,17 +41,18 @@ let questionStartMS = 0; $(document).ready(function() { //$("#retryButton").toggleClass("on"); //alert($('li[data-keycode="test"]').attr('id')); - $.getJSON( "scripts/shortcuts.json", function( data ) { - allData = data; - if(localStorage.getItem("questionNo")==null){ + fetch('scripts/shortcuts.json') + .then(response => response.json()) + .then(data => { + allData=data + if(localStorage.getItem("questionNo")==null) + { localStorage.setItem("questionNo", "1"); localStorage.setItem("totalCount", Object.keys(allData).length); } - // Call readText() - readText() - - updateTimingDisplay(); - }) + readText() + updateTimingDisplay() + }); $('.container').css('height', $(window).height()); $(window).on('resize', function() { From 2e06d3ad9da6e1475ca50e145949678e33ba930e Mon Sep 17 00:00:00 2001 From: Beleicia Bullock <10715618+belebull@users.noreply.github.com> Date: Thu, 1 Oct 2020 19:11:31 -0500 Subject: [PATCH 28/56] feat: add shortcut type tag to JSON object and main screen (#103) --- public/CSS/main.css | 13 ++++- public/scripts/main.js | 9 ++++ public/scripts/shortcuts.json | 96 +++++++++++++++++++++++------------ views/index.ejs | 1 + 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/public/CSS/main.css b/public/CSS/main.css index 8e007d2..6fce138 100644 --- a/public/CSS/main.css +++ b/public/CSS/main.css @@ -72,7 +72,7 @@ body { } .cheatsheet { - margin-top: 20px; + margin-top: 15px; } .img-button { @@ -194,4 +194,15 @@ div .arrows{ padding: 1em; border-radius: 4px; margin: -1.5em 1em 0em 1em; +} + +#shortcut-tag{ + border-radius: 50px; + color: #ffffff; + font-size: 12px; + margin-top: 30px; + padding: 3px 10px; + text-align: center; + text-transform: capitalize; + width: 100px; } \ No newline at end of file diff --git a/public/scripts/main.js b/public/scripts/main.js index 53a5312..cd79916 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -172,6 +172,7 @@ function readText(){ if(quesNo!=null){ commandText = allData[parseInt(quesNo)-1].answer answerkeys = allData[parseInt(quesNo)-1].keys + type = allData[parseInt(quesNo) - 1].shortcutType //commandText = "A+Control" //$("#textdiv").text(); // Will be taken from some other list type of a source. //Each command will have an associated question text used in writeQuestion var speed = 50 @@ -186,6 +187,14 @@ function readText(){ promptKey2(val) }); + // update shortcut type + $('#shortcut-tag').first().text(type + ' Shortcut') + if(type == 'mac') { + $('#shortcut-tag').first().css('background-color', '#3455db') + } else { + $('#shortcut-tag').first().css('background-color', '#4b2142') + } + /* commandText.split('+').forEach(function(c) { if(c.toLowerCase()=="command"){ reqKeys.push("meta") diff --git a/public/scripts/shortcuts.json b/public/scripts/shortcuts.json index c80503e..5002388 100644 --- a/public/scripts/shortcuts.json +++ b/public/scripts/shortcuts.json @@ -2,161 +2,193 @@ { "answer": "command+x", "question": "How do you cut the selected item and copy it to the clipboard?", - "keys": [91, 88] + "keys": [91, 88], + "shortcutType": "mac" }, { "answer": "command+c", "question": "How do you copy the selected item to the clipboard?", - "keys": [91, 67] + "keys": [91, 67], + "shortcutType": "mac" }, { "answer": "command+v", "question": "How do you paste the contents of the clipboard into the current document or app?", - "keys": [91, 86] + "keys": [91, 86], + "shortcutType": "mac" }, { "answer": "command+z", "question": "How do you undo the previous command?", - "keys": [91, 90] + "keys": [91, 90], + "shortcutType": "mac" }, { "answer": "command+Shift+z", "question": "How do you redo to reverse the undo command?", - "keys": [91, 16, 90] + "keys": [91, 16, 90], + "shortcutType": "mac" }, { "answer": "command+a", "question": "How do you select all items?", - "keys": [91, 65] + "keys": [91, 65], + "shortcutType": "mac" }, { "answer": "command+f", "question": "How do you find items in a document or open a Find window?", - "keys": [91, 70] + "keys": [91, 70], + "shortcutType": "mac" }, { "answer": "command+g", "question": "How do you find the next occurrence of the item previously found?", - "keys": [91, 71] + "keys": [91, 71], + "shortcutType": "mac" }, { "answer": "command+h", "question": "How do you hide the windows of the front (active) app?", - "keys": [91, 72] + "keys": [91, 72], + "shortcutType": "mac" }, { "answer": "command+Option+h", "question": "How do you view the front (active) app but hide all other apps?", - "keys": [91, 18, 72] + "keys": [91, 18, 72], + "shortcutType": "mac" }, { "answer": "command+k", "question": "How do you clear the screen using the command key?", - "keys": [91, 75] + "keys": [91, 75], + "shortcutType": "mac" }, { "answer": "command+m", "question": "How do you minimize the front window to the Dock?", - "keys": [91, 77] + "keys": [91, 77], + "shortcutType": "mac" }, { "answer": "command+Option+m", "question": "How do you minimize all windows of the front app?", - "keys": [91, 18, 77] + "keys": [91, 18, 77], + "shortcutType": "mac" }, { "answer": "command+n", "question": "How do you open a new document or window?", - "keys": [91, 78] + "keys": [91, 78], + "shortcutType": "mac" }, { "answer": "command+t", "question": "How do you open a new tab?", - "keys": [91, 84] + "keys": [91, 84], + "shortcutType": "mac" }, { "answer": "command+o", "question": "How do you open the selected item, or open a dialog to select a file to open?", - "keys": [91, 79] + "keys": [91, 79], + "shortcutType": "mac" }, { "answer": "command+p", "question": "How do you print the current document?", - "keys": [91, 80] + "keys": [91, 80], + "shortcutType": "mac" }, { "answer": "command+s", "question": "How do you save the current document?", - "keys": [91, 83] + "keys": [91, 83], + "shortcutType": "mac" }, { "answer": "Option+command+Esc", "question": "How do you force quit?", - "keys": [18, 91, 27] + "keys": [18, 91, 27], + "shortcutType": "mac" }, { "answer": "command+Space", "question": "How do you show or hide the Spotlight search field?", - "keys": [91, 32] + "keys": [91, 32], + "shortcutType": "mac" }, { "answer": "command+Tab", "question": "How do you switch to the next most recently used app among your open apps?", - "keys": [91, 9] + "keys": [91, 9], + "shortcutType": "mac" }, { "answer": "Shift+command+Tilde(~)", "question": "How do you switch to the next most recently used window of the front app?", - "keys": [16 ,91, 192] + "keys": [16 ,91, 192], + "shortcutType": "mac" }, { "answer": "control+a", "question": "How do you go to the beginning of the line you are currently typing on?", - "keys": [17, 65] + "keys": [17, 65], + "shortcutType": "shell" }, { "answer": "control+e", "question": "How do you go to the end of the line you are currently typing on?", - "keys": [17, 69] + "keys": [17, 69], + "shortcutType": "shell" }, { "answer": "control+q", "question": "How do you clear everything on the current line?", - "keys": [17, 81] + "keys": [17, 81], + "shortcutType": "shell" }, { "answer": "control+l", "question": "How do you clear the screen using the control key?", - "keys": [17, 76] + "keys": [17, 76], + "shortcutType": "shell" }, { "answer": "control+k", "question": "How do you cut everything forward to the end of the line?", - "keys": [17, 75] + "keys": [17, 75], + "shortcutType": "shell" }, { "answer": "control+u", "question": "How do you cut everything backwards to the beginning of the line?", - "keys": [17, 85] + "keys": [17, 85], + "shortcutType": "shell" }, { "answer": "control+w", "question": "How do you cut one word backwards using white space as the delimiter?", - "keys": [17, 87] + "keys": [17, 87], + "shortcutType": "shell" }, { "answer": "control+y", "question": "How do you paste whatever was cut by the last cut command?", - "keys": [17, 89] + "keys": [17, 89], + "shortcutType": "shell" }, { "answer": "Shift+command+3", "question": "How do you take a screenshot of the entire screen?", - "keys": [16 ,91, 51] + "keys": [16 ,91, 51], + "shortcutType": "mac" }, { "answer": "command+Comma(,)", "question": "How do you open preferences for the front app?", - "keys": [91, 188] + "keys": [91, 188], + "shortcutType": "mac" } ] diff --git a/views/index.ejs b/views/index.ejs index 8644711..77c0e96 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -22,6 +22,7 @@
+
Mac Shortcut
Cheat Sheet
From 6b93706bed210979db38b3bfbcbea4b413cdee17 Mon Sep 17 00:00:00 2001 From: Izzy Berzsenyi Date: Thu, 1 Oct 2020 19:49:10 -0500 Subject: [PATCH 29/56] Addressing code review comments --- .env.example | 2 +- JS/auth0.js | 15 ++++----------- README.md | 2 +- app.js | 6 +++--- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/.env.example b/.env.example index 68c1f29..910ce35 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ DB_URL=dev mode defaults to sqlite (so this is not needed) AUTH0_CLIENT_ID=YOUR_CLIENT_ID -AUTH0_SECRET=YOU_CLIENT_SECRET +AUTH0_SECRET=YOUR_CLIENT_SECRET AUTH0_ISSUER_BASE_URL=APPLICATION_TENANT_DOMAIN_URL diff --git a/JS/auth0.js b/JS/auth0.js index c59eb99..553fb11 100644 --- a/JS/auth0.js +++ b/JS/auth0.js @@ -1,24 +1,17 @@ const { AUTH0_SECRET, AUTH0_CLIENT_ID, AUTH0_ISSUER_BASE_URL } = process.env; const port = process.env.port || 3000; -let auth_config = undefined; +let authConfig = undefined; -const secretGiven = () => AUTH0_SECRET != undefined; -const idGiven = () => AUTH0_CLIENT_ID != undefined; const isValidUrl = () => { try { new URL(AUTH0_ISSUER_BASE_URL); } catch (_) { return false; } - if (string.startsWith("https://")) { - return true - } else { - throw new Error("Auth0 issuer base url is not valid, must begin with 'https://'"); - } } -if (secretGiven && idGiven && isValidUrl) { - auth_config = { +if (AUTH0_SECRET != undefined && AUTH0_CLIENT_ID != undefined && isValidUrl) { + authConfig = { authRequired: false, auth0Logout: true, issuerBaseURL: AUTH0_ISSUER_BASE_URL, @@ -29,5 +22,5 @@ if (secretGiven && idGiven && isValidUrl) { } module.exports = { - auth_config + authConfig }; diff --git a/README.md b/README.md index b77d313..103c1a1 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ can sign in, practice with the app, and save their progress. That way, the next # Setting up Auth0 and creating an account 1. Create a [free personal Auth0 account](https://auth0.com/) 1. Create a `Regular Web Application` -1. Run `mv .env.example .env` to create a .env file +1. Run `cp .env.example .env` to create a .env file 1. From the settings page of your Auth0 web application fill in the environment variables, ensuring that the `AUTH0_ISSUER_BASE_URL` is the Domain URL starting with `https://` ## Running the project diff --git a/app.js b/app.js index ca1b76f..ecb5b18 100644 --- a/app.js +++ b/app.js @@ -4,7 +4,7 @@ const express = require("express"); const bodyParser = require("body-parser"); const { auth } = require('express-openid-connect'); const { connectToDb } = require("./JS/orm"); -const { auth_config } = require("./JS/auth0"); +const { authConfig } = require("./JS/auth0"); const app = express(); app.use(morgan("dev")); //morgan gives us useful logging @@ -17,8 +17,8 @@ app.use(express.static("public")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); -if (auth_config != undefined) { - app.use(auth(auth_config)); // auth router attaches /login, /logout, and /callback routes to the baseURL +if (authConfig) { + app.use(auth(authConfig)); // auth router attaches /login, /logout, and /callback routes to the baseURL } const routes = require("./routes/routes.js"); From 5daad7e6ece83b446fc9f3e6aa30fe890a8d4020 Mon Sep 17 00:00:00 2001 From: Linh Date: Fri, 2 Oct 2020 03:16:32 +0000 Subject: [PATCH 30/56] Replace jQuery.text function --- public/scripts/main.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index cd79916..797de08 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -147,9 +147,9 @@ function release(e) { // May have to be removed. Not being used currently function highlightNextKey(params){ $("#"+nxt.toLowerCase()).toggleClass("pressed"); - - - + // + // + // } function promptKey2(key){ @@ -173,7 +173,7 @@ function readText(){ commandText = allData[parseInt(quesNo)-1].answer answerkeys = allData[parseInt(quesNo)-1].keys type = allData[parseInt(quesNo) - 1].shortcutType - //commandText = "A+Control" //$("#textdiv").text(); // Will be taken from some other list type of a source. + //commandText = "A+Control" // document.querySelector("#textdiv").textContent; // Will be taken from some other list type of a source. //Each command will have an associated question text used in writeQuestion var speed = 50 var i = 0; @@ -188,7 +188,7 @@ function readText(){ }); // update shortcut type - $('#shortcut-tag').first().text(type + ' Shortcut') + document.querySelector("#shortcut-tag").textContent = type + " Shortcut"; if(type == 'mac') { $('#shortcut-tag').first().css('background-color', '#3455db') } else { @@ -216,7 +216,7 @@ function readText(){ function writeQuestion(question) { if(typewriter!=null) { typewriter.state.eventQueue = []; - $('#textdiv span').first().text(''); + document.querySelector("#textdiv span").textContent = ''; } else { typewriter = new Typewriter(document.getElementById('textdiv'), { loop: false, @@ -307,7 +307,7 @@ function onSuccess() { handleTimingFeedback(questionNo, thisAnswerMS); recordAnswer(questionNo, thisAnswerMS); saveHistory(); - $('#textdiv span').first().text('Correct Keys pressed!'); + document.querySelector("#textdiv span").textContent = 'Correct Keys pressed!'; clearPromptKeys(); clearPressedKeys(); confetti($("#confetti").get(0), { spread: 180, startVelocity: 50, elementCount: 150 }); From 9ecb64ba413bd106c95434dfcf243fead1e14ad7 Mon Sep 17 00:00:00 2001 From: Aryan Verma Date: Fri, 2 Oct 2020 16:31:08 +0530 Subject: [PATCH 31/56] fixed issues with in-built DOM selector --- public/scripts/main.js | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 25aaf76..3ee6a82 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -113,13 +113,17 @@ function handle(e) { $("#"+e.key.toLowerCase()).toggleClass("pressed"); $('.letter').toggleClass('uppercase'); } - else document.querySelector("#"+e.key.toLowerCase() ).classList.add("pressed"); + else{ + if(document.querySelector("#"+e.key.toLowerCase() )) + document.querySelector("#"+e.key.toLowerCase() ).classList.add("pressed"); + } } // Function called on KeyUp to reset the key by removing class = 'pressed' function release(e) { if((e.which>=186 && e.which<=192)|| (e.which>=219 && e.which<=222)){ - document.querySelector("#"+e.code.toLowerCase()).classList.remove("pressed"); + if(document.querySelector("#"+e.code.toLowerCase())) + document.querySelector("#"+e.code.toLowerCase()).classList.remove("pressed"); } if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ let keyString = e.code; @@ -128,10 +132,12 @@ function release(e) { } else if (e.code == FIREFOX_RIGHT_COMMAND_STRING) { keyString = CHROME_RIGHT_COMMAND_STRING } - document.querySelector("#"+keyString.toLowerCase()).classList.remove("pressed"); + if(document.querySelector("#"+keyString.toLowerCase())) + document.querySelector("#"+keyString.toLowerCase()).classList.remove("pressed"); } if(e.code.toLowerCase()=="space"){ - document.querySelector("#space").classList.remove("pressed"); + if(document.querySelector("#space")) + document.querySelector("#space").classList.remove("pressed"); } if(e.key.toLowerCase()=="capslock"){ $("#"+e.key.toLowerCase()).toggleClass("pressed"); @@ -139,7 +145,8 @@ function release(e) { caps=false; } else{ - document.querySelector("#"+e.key.toLowerCase() ).classList.remove("pressed"); + if(document.querySelector("#"+e.key.toLowerCase() )) + document.querySelector("#"+e.key.toLowerCase() ).classList.remove("pressed"); } } @@ -220,16 +227,19 @@ function writeQuestion(question) { } function clearIncorrectIndication() { - document.querySelector("#read").classList.remove('incorrect'); + if(document.querySelector("#read")) + document.querySelector("#read").classList.remove('incorrect'); }; function clearPromptKeys() { - document.querySelector('.prompt').classList.remove('prompt'); + if(document.querySelector('.prompt')) + document.querySelector('.prompt').classList.remove('prompt'); }; function clearPressedKeys() { pressed.clear(); - document.querySelector('.pressed').classList.remove('pressed'); + if(document.querySelector('.pressed')) + document.querySelector('.pressed').classList.remove('pressed'); }; function updateTimingDisplay() { @@ -253,7 +263,8 @@ function updateTimingDisplay() { function onIncorrect() { $('#textdiv').effect("shake", { distance: 3 }); - document.querySelector("#read").classList.add('incorrect'); + if(document.querySelector("#read")) + document.querySelector("#read").classList.add('incorrect'); setTimeout(clearPressedKeys, 500); }; From 423355d4c0253902af7e63381c50d14297ce9707 Mon Sep 17 00:00:00 2001 From: frankyfrankfrank Date: Thu, 1 Oct 2020 21:10:25 -0400 Subject: [PATCH 32/56] remove window height listener in favour of css container height value from 800px to 100vh remove unneeded window height listener container height is already set by the css value --- public/CSS/main.css | 2 +- public/scripts/main.js | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/public/CSS/main.css b/public/CSS/main.css index 6fce138..b3bd964 100644 --- a/public/CSS/main.css +++ b/public/CSS/main.css @@ -1,5 +1,5 @@ .container { - height: 800px; + height: 100vh; margin: 0px auto; } diff --git a/public/scripts/main.js b/public/scripts/main.js index cd79916..6c30ef8 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -53,11 +53,6 @@ $(document).ready(function() { readText() updateTimingDisplay() }); - - $('.container').css('height', $(window).height()); - $(window).on('resize', function() { - $('.container').css('height', $(window).height()); - }); }); function nextQuestion() { From 2be3bae2c73edf96bc62da085fb5e620b03abeed Mon Sep 17 00:00:00 2001 From: Dimitrij Agal Date: Sun, 4 Oct 2020 02:20:37 +0700 Subject: [PATCH 33/56] feat: add toggle to show/hide button hint (#127) --- public/CSS/main.css | 16 ++++++++++++++++ public/scripts/main.js | 24 ++++++++++++++++++++---- views/index.ejs | 4 ++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/public/CSS/main.css b/public/CSS/main.css index b3bd964..69cb24e 100644 --- a/public/CSS/main.css +++ b/public/CSS/main.css @@ -205,4 +205,20 @@ div .arrows{ text-align: center; text-transform: capitalize; width: 100px; +} + +#hint-checkbox-container { + width: 100%; + text-align: right; + margin-bottom: 1rem; + font-size: 0.8rem; +} + +#hint-checkbox-container span { + vertical-align: text-bottom; +} + +#hint-checkbox-container #show-hint { + height: 1rem; + width: 1rem; } \ No newline at end of file diff --git a/public/scripts/main.js b/public/scripts/main.js index fe5866e..6cd0aa2 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -5,6 +5,7 @@ var reqKeys = [] var typewriter; var quesNo; let pressed = new Set(); +let isShowHint = true; // event.keyCode Chrome and Firefox const CHROME_LEFT_COMMAND_CODE = 91; @@ -157,7 +158,11 @@ function highlightNextKey(params){ function promptKey2(key){ //if($('li[data-keycode="'+key+'"]'[0]).hasClass('prompt')){ - $($('li[data-keycode="'+key+'"]')[0]).toggleClass("prompt") + if (isShowHint) { + $($('li[data-keycode="'+key+'"]')[0]).addClass("prompt") + } else { + $($('li[data-keycode="'+key+'"]')[0]).removeClass("prompt") + } //} } @@ -169,8 +174,11 @@ function promptKey(key){ if (id) $('#' + id).toggleClass('prompt'); } -// Function to read the next combination of keys and highlight it on keyboard -function readText(){ +/** + * Function to read the next combination of keys and highlight it on keyboard + * @param withoutAnimation {boolean=} [withoutAnimation = false] flag to prevent typing question animation + */ +function readText(withoutAnimation){ quesNo = localStorage.getItem("questionNo") if(quesNo!=null){ commandText = allData[parseInt(quesNo)-1].answer @@ -182,7 +190,9 @@ function readText(){ var i = 0; // Call writeQuestion to add question on the top textarea - writeQuestion(allData[parseInt(localStorage.getItem("questionNo"))-1].question) + if (!withoutAnimation) { + writeQuestion(allData[parseInt(localStorage.getItem("questionNo"))-1].question) + } $.each(answerkeys , function(index, val) { reqKeys.push(val) @@ -392,6 +402,12 @@ window.addEventListener('focus', function (e) { } }); +const showHintCheckbox = document.getElementById('show-hint'); +showHintCheckbox.addEventListener('change', function(e) { + isShowHint = e.target.checked; + readText(true) +}) + function createUserAnswer(questionNo, isCorrect, elapsedTimeMs){ let requestBody = { userId: 'guest', diff --git a/views/index.ejs b/views/index.ejs index 77c0e96..6705ffd 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -32,6 +32,10 @@
+
+ + Show Hint +
  • esc
  • F1
  • From 46c4e4de55cbf0141a27ad51af176bf7c53d21c5 Mon Sep 17 00:00:00 2001 From: Anurag sati <52669445+anuragsati@users.noreply.github.com> Date: Sun, 4 Oct 2020 00:56:01 +0530 Subject: [PATCH 34/56] Updated ecstatic to v 4.1.4 (#126) --- package-lock.json | 48 +++++++++++++++++++++++++++++++++++++++-------- package.json | 1 + 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index fa40910..dcc40ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -469,6 +469,11 @@ "supports-color": "^5.3.0" } }, + "charset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/charset/-/charset-1.0.1.tgz", + "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==" + }, "chokidar": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", @@ -741,14 +746,23 @@ } }, "ecstatic": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", - "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-4.1.4.tgz", + "integrity": "sha512-8E4ZLK4uRuB9pwywGpy/B9vcz4gCp6IY7u4cMbeCINr/fjb1v+0wf0Ae2XlfSnG8xZYnE4uaJBjFkYI0bqcIdw==", "requires": { + "charset": "^1.0.1", "he": "^1.1.1", - "mime": "^1.6.0", + "mime": "^2.4.1", "minimist": "^1.1.0", - "url-join": "^2.0.5" + "on-finished": "^2.3.0", + "url-join": "^4.0.0" + }, + "dependencies": { + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" + } } }, "ee-first": { @@ -1225,6 +1239,24 @@ "optimist": "0.6.x", "portfinder": "^1.0.13", "union": "~0.4.3" + }, + "dependencies": { + "ecstatic": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", + "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "requires": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + } + }, + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" + } } }, "http-signature": { @@ -3043,9 +3075,9 @@ } }, "url-join": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", - "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" }, "url-parse-lax": { "version": "3.0.0", diff --git a/package.json b/package.json index 276c96e..0df1f84 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "homepage": "https://github.com/Techtonica/keyboard-shortcuts-practice#readme", "dependencies": { "dotenv": "^8.1.0", + "ecstatic": "^4.1.4", "ejs": "^3.0.1", "express": "^4.17.1", "http-server": "^0.11.1", From c031664c5dab181f6e8745f389b6f864b59cc395 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Tue, 6 Oct 2020 19:40:19 -0400 Subject: [PATCH 35/56] get last 3 timing given the user and question id endpoint --- routes/routes.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/routes/routes.js b/routes/routes.js index b133d8c..c5e08a9 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -38,5 +38,31 @@ router.post('/user/answers/question/:questionNumber', (req, res) => { }) }) +router.get('/user/answers/question/:questionNumber', (req, res) => { + let pageSize = 3; // TODO: define it in more stadarized way + + User.findOne({ + where: {id: req.body.userId} + }).then(user => { + + UserAnswers.findAll({ + where: {question_number: req.params.questionNumber, user_id: user.id}, + order: [ + ['created_at', 'DESC'] + ], + limit: pageSize + }).then(userAnswers => { + return res.json({ + previousTimingMs: userAnswers.map(userAnswer => userAnswer.elapsed_time_ms) + }) + }).catch(error => { + console.log(error); + return res.status(400).json(error.errors) // TODO: handle better error messages + }) + }).catch(error => { + console.log(error); + return res.status(400).json({message: "User doesn't exists."}) // TODO: handle better error messages + }) +}) module.exports = router; From 2a37b913adccee70757c9ca4fefc637b96d14362 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Tue, 6 Oct 2020 21:29:33 -0400 Subject: [PATCH 36/56] - integrated history endpoint - param in query instead of body in endpoint request --- public/scripts/history.js | 18 ++++++-- public/scripts/main.js | 87 ++++++++++++++++++++------------------- routes/routes.js | 4 +- 3 files changed, 61 insertions(+), 48 deletions(-) diff --git a/public/scripts/history.js b/public/scripts/history.js index 2d9e015..8c63396 100644 --- a/public/scripts/history.js +++ b/public/scripts/history.js @@ -72,14 +72,26 @@ function clearHistory() { } // returns an array with timing data for a given question number -function getHistory(questionNo) { +async function getHistory(questionNo) { if (!loadHistory()) { console.error('Unable to load history for question ' + questionNo); return []; } - var record = _history[questionNo]; - return !!record ? record : []; + let url = new URL(document.URL + 'user/answers/question/' + questionNo); + let params = { + userId: 'guest' // TODO: get actual userId + } + url.search = new URLSearchParams(params).toString(); + + try{ + let response = await fetch(url); + let body = await response.json(); + return body.previousTimingMs; + }catch(error){ + console.error(error); + return []; + } } // record the time taken to answer a given question based on the question diff --git a/public/scripts/main.js b/public/scripts/main.js index 6cd0aa2..4706ad2 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -263,19 +263,19 @@ function updateTimingDisplay() { $('#timing-feedback').html(''); var questionNo = localStorage.getItem('questionNo'); // grab the last bits of timing data - var timings = getHistory(questionNo).slice(-3); - - // and then drop them into the boxes - timings.forEach(function(t, idx) { - var element = $('#timing-' + idx); - element.html(t / 1000 + ' sec'); - element.show(); - }) - - // hide the boxes if we don't have timing data - for (var i = timings.length; i < 3; i++) { - $('#timing-' + i).hide(); - } + getHistory(questionNo).then(timings => { + // and then drop them into the boxes + timings.forEach(function(t, idx) { + var element = $('#timing-' + idx); + element.html(t / 1000 + ' sec'); + element.show(); + }) + + // hide the boxes if we don't have timing data + for (var i = timings.length; i < 3; i++) { + $('#timing-' + i).hide(); + } + }); } function onIncorrect() { @@ -286,36 +286,37 @@ function onIncorrect() { }; function handleTimingFeedback(questionNo, curMS) { - var previousTimings = getHistory(questionNo); - if (previousTimings.length == 0) { - return; - } - - var average = previousTimings.reduce( - function(acc, cur) { return acc + cur }, - 0, - ) / previousTimings.length; - - var delta = average - curMS; - - var template = null; - if (delta > 0) { - template = "
    You were faster by ${delta} sec!"; - } - if (delta < 0) { - template = "
    You were slower by ${delta} sec."; - } - if (template === null) { - return; - } - - // convert MS to S - delta = Math.abs(delta) / 1000; - // now we want to trunate to 2 decimals; the `+` will let us only use 2 - // decimals if we actually need them, e.g., we want 1.5 not 1.50 - // cf. https://stackoverflow.com/a/12830454 - delta = +delta.toFixed(2); - $('#timing-feedback').html(template.replace('${delta}', delta)); + getHistory(questionNo).then(previousTimings => { + if (previousTimings.length == 0) { + return; + } + + var average = previousTimings.reduce( + function(acc, cur) { return acc + cur }, + 0, + ) / previousTimings.length; + + var delta = average - curMS; + + var template = null; + if (delta > 0) { + template = "
    You were faster by ${delta} sec!"; + } + if (delta < 0) { + template = "
    You were slower by ${delta} sec."; + } + if (template === null) { + return; + } + + // convert MS to S + delta = Math.abs(delta) / 1000; + // now we want to trunate to 2 decimals; the `+` will let us only use 2 + // decimals if we actually need them, e.g., we want 1.5 not 1.50 + // cf. https://stackoverflow.com/a/12830454 + delta = +delta.toFixed(2); + $('#timing-feedback').html(template.replace('${delta}', delta)); + }); } // Function to execute when correct keys are pressed. diff --git a/routes/routes.js b/routes/routes.js index c5e08a9..ee29184 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -42,7 +42,7 @@ router.get('/user/answers/question/:questionNumber', (req, res) => { let pageSize = 3; // TODO: define it in more stadarized way User.findOne({ - where: {id: req.body.userId} + where: {id: req.query.userId} }).then(user => { UserAnswers.findAll({ @@ -52,7 +52,7 @@ router.get('/user/answers/question/:questionNumber', (req, res) => { ], limit: pageSize }).then(userAnswers => { - return res.json({ + return res.status(200).json({ previousTimingMs: userAnswers.map(userAnswer => userAnswer.elapsed_time_ms) }) }).catch(error => { From 3a651b1eb77564dbafd254df5dceec0a32180c68 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Tue, 6 Oct 2020 21:46:37 -0400 Subject: [PATCH 37/56] refactored history.js --- public/scripts/history.js | 95 +-------------------------------------- public/scripts/main.js | 2 - 2 files changed, 2 insertions(+), 95 deletions(-) diff --git a/public/scripts/history.js b/public/scripts/history.js index 8c63396..5d3ea57 100644 --- a/public/scripts/history.js +++ b/public/scripts/history.js @@ -1,111 +1,20 @@ -// global reference to the history; shouldn't be directly accessed outside -// this file. -// -// If we are using a remote backend cache the value here for easy access once -// we've done an initial retrieval -var _history = null; - -// this tracks if we're using local storage or some remote user system to -// keep timing data -var _historyUsesLocalStorage = true; - -// the key we store timing data under when in local storage mode -var _historyKey = 'response_history'; - /////////////////////////////////////////////////////////////////////////////// -// If we are storing things remotely the code to get them goes here -function getRemoteHistory() { - console.error('User accounts not yet implemented.'); - return null; -} - -// as above except saving -function saveRemoteHistory() { - console.error('User accounts not yet implementhed.'); - return false; -} - -// ensures that history has been loaded; returns true on success -function loadHistory() { - if (_history !== null) { - return true; - } - - if (!_historyUsesLocalStorage) { - var history = getRemoteHistory(); - if (history === null) { - console.error('Falling back to local history'); - } else { - _history = history; - return true; - } - } - - var history = localStorage.getItem(_historyKey); - if (history == null) { - localStorage.setItem(_historyKey, JSON.stringify({})); - history = "{}"; - } - _history = JSON.parse(history); - return true; -} - -// saves history; returns true on success -function saveHistory() { - if (!_historyUsesLocalStorage) { - if (saveRemoteHistory()) { - return true; - } - console.error('Falling back to local history'); - } - - localStorage.setItem(_historyKey, JSON.stringify(_history)); - return true; -} - -// clears historic timing data and saves the cleared state; returns true on -// success -function clearHistory() { - _history = {}; - return saveHistory(); -} - // returns an array with timing data for a given question number async function getHistory(questionNo) { - if (!loadHistory()) { - console.error('Unable to load history for question ' + questionNo); - return []; - } - let url = new URL(document.URL + 'user/answers/question/' + questionNo); let params = { userId: 'guest' // TODO: get actual userId } url.search = new URLSearchParams(params).toString(); - + try{ let response = await fetch(url); let body = await response.json(); return body.previousTimingMs; + }catch(error){ console.error(error); return []; } } - -// record the time taken to answer a given question based on the question -// number -function recordAnswer(questionNo, timeSpentMS) { - if (!loadHistory()) { - console.error('Unable to record new time for question ' + questionNo); - return false; - } - - // check for existing timing data, initialize if none found - if (!_history[questionNo]) { - _history[questionNo] = []; - } - _history[questionNo].push(timeSpentMS); - return true; -} \ No newline at end of file diff --git a/public/scripts/main.js b/public/scripts/main.js index 4706ad2..095ba59 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -324,8 +324,6 @@ function onSuccess() { var questionNo = localStorage.getItem("questionNo"); var thisAnswerMS = Date.now() - questionStartMS; handleTimingFeedback(questionNo, thisAnswerMS); - recordAnswer(questionNo, thisAnswerMS); - saveHistory(); document.querySelector("#textdiv span").textContent = 'Correct Keys pressed!'; clearPromptKeys(); clearPressedKeys(); From 4db476be006af5f06617256a6dc7fc17d0739330 Mon Sep 17 00:00:00 2001 From: Mayra Lucia Navarro Date: Wed, 7 Oct 2020 04:33:22 -0500 Subject: [PATCH 38/56] fix: split list keyboard per row (#134) change styles to avoid breaks per row --- public/CSS/main.css | 7 ++++++- views/index.ejs | 18 +++++++++++++++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/public/CSS/main.css b/public/CSS/main.css index 69cb24e..914aba1 100644 --- a/public/CSS/main.css +++ b/public/CSS/main.css @@ -99,10 +99,15 @@ body { -webkit-border-radius: 5px; margin: 0; padding: 2px; - list-style: none; overflow:auto; font-family: 'Roboto', sans-serif;; } +#keyboard ul.row { + display: flex; + list-style: none; + margin: 0; + padding: 0; +} #keyboard li { float: left; diff --git a/views/index.ejs b/views/index.ejs index 6705ffd..06a7c2c 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -36,7 +36,8 @@ Show Hint
-
    +
    +
    • esc
    • F1
    • F2
    • @@ -51,6 +52,8 @@
    • F11
    • F12
    • TBD
    • +
    +
    • ~
      `
      ~`
    • !
      1
      !1
    • @
      2
      @2
    • @@ -65,6 +68,8 @@
    • _
      -
      _-
    • +
      =
      +=
    • delete
    • +
    +
    • tab
    • q
    • w
    • @@ -79,6 +84,8 @@
    • {
      [
    • ]
      }
    • |
      \
    • +
    +
    • caps lock
    • a
    • s
    • @@ -92,6 +99,8 @@
    • :
      ;
      ;:
    • '
      "
      '"
    • return
    • +
    +
    • shift
    • z
    • x
    • @@ -104,6 +113,8 @@
    • >
      .
      .>
    • ?
      /
      /?
    • shift
    • +
    +
    • fn
    • control
    • option
    • @@ -112,9 +123,10 @@
    • command
    • option
    • -
    • +
    • +
    • -
    • +
From d2d385518f51f606713445285ce4b3378cd4da5a Mon Sep 17 00:00:00 2001 From: Kat Shambaugh <44981851+KatShambaugh@users.noreply.github.com> Date: Wed, 7 Oct 2020 05:49:34 -0400 Subject: [PATCH 39/56] fix: Command hotkeys escaped instead of executed #45 (#118) --- package-lock.json | 83 +++++++++++++++++------------------------- package.json | 2 +- public/scripts/main.js | 23 ++++++++++-- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/package-lock.json b/package-lock.json index dcc40ed..5298b6e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -544,9 +544,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, "combined-stream": { "version": "1.0.8", @@ -1031,7 +1031,6 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "optional": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -1227,35 +1226,26 @@ } }, "http-server": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz", - "integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==", - "requires": { - "colors": "1.0.3", - "corser": "~2.0.0", - "ecstatic": "^3.0.0", - "http-proxy": "^1.8.1", - "opener": "~1.4.0", - "optimist": "0.6.x", - "portfinder": "^1.0.13", - "union": "~0.4.3" + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", + "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", + "requires": { + "basic-auth": "^1.0.3", + "colors": "^1.4.0", + "corser": "^2.0.1", + "ecstatic": "^3.3.2", + "http-proxy": "^1.18.0", + "minimist": "^1.2.5", + "opener": "^1.5.1", + "portfinder": "^1.0.25", + "secure-compare": "3.0.1", + "union": "~0.5.0" }, "dependencies": { - "ecstatic": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", - "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", - "requires": { - "he": "^1.1.1", - "mime": "^1.6.0", - "minimist": "^1.1.0", - "url-join": "^2.0.5" - } - }, - "url-join": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", - "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" + "basic-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" } } }, @@ -1978,9 +1968,9 @@ } }, "opener": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", - "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=" + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" }, "openid-client": { "version": "4.1.1", @@ -2594,6 +2584,11 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, + "secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=" + }, "semver": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", @@ -2965,18 +2960,11 @@ "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==" }, "union": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz", - "integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", "requires": { - "qs": "~2.3.3" - }, - "dependencies": { - "qs": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", - "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=" - } + "qs": "^6.4.0" } }, "unique-string": { @@ -3189,11 +3177,6 @@ "@types/node": "*" } }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 0df1f84..9b2e74f 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "ecstatic": "^4.1.4", "ejs": "^3.0.1", "express": "^4.17.1", - "http-server": "^0.11.1", + "http-server": "^0.12.3", "express-openid-connect": "^2.0.0", "morgan": "^1.9.1", "mysql": "^2.17.1", diff --git a/public/scripts/main.js b/public/scripts/main.js index 6cd0aa2..5dc05dd 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -5,6 +5,7 @@ var reqKeys = [] var typewriter; var quesNo; let pressed = new Set(); +let commandDown = false; let isShowHint = true; // event.keyCode Chrome and Firefox @@ -97,6 +98,9 @@ function handle(e) { $("#"+e.code.toLowerCase()).toggleClass("pressed"); } if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ + if (e.key.toLowerCase()=="meta") { + commandDown = true; + } let keyString = e.code; if(e.code == FIREFOX_LEFT_COMMAND_STRING) { keyString = CHROME_LEFT_COMMAND_STRING @@ -110,9 +114,19 @@ function handle(e) { $("#"+e.key.toLowerCase()).toggleClass("pressed"); $('.letter').toggleClass('uppercase'); } - else{ - if(document.querySelector("#"+e.key.toLowerCase() )) - document.querySelector("#"+e.key.toLowerCase() ).classList.add("pressed"); + else if(e.key.toLowerCase()=="capslock" && caps==true) { + $("#"+e.key.toLowerCase()).toggleClass("pressed"); + $('.letter').toggleClass('uppercase'); + caps=false; + } + else { + if (commandDown) { + e.preventDefault(); + e.stopPropagation(); + $("#"+e.key.toLowerCase() ).addClass("pressed"); + return false; + } + $("#"+e.key.toLowerCase() ).addClass("pressed"); } } @@ -123,6 +137,9 @@ function release(e) { document.querySelector("#"+e.code.toLowerCase()).classList.remove("pressed"); } if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ + if (e.key.toLowerCase()=="meta") { + commandDown = false; + } let keyString = e.code; if(e.code == FIREFOX_LEFT_COMMAND_STRING) { keyString = CHROME_LEFT_COMMAND_STRING From 1bd95a022e8d5aff6da5f6840a8e99cfd2652e17 Mon Sep 17 00:00:00 2001 From: Ybrahin Martinez Date: Wed, 7 Oct 2020 13:19:34 -0400 Subject: [PATCH 40/56] Refactor the jquery functions in main.js --- public/scripts/main.js | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 5dc05dd..f283612 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -92,10 +92,11 @@ function handle(e) { ' code=' + e.code if(e.code.toLowerCase()=="space"){ - $("#space").toggleClass("pressed"); + document.querySelector('#space').classList.toggle("pressed"); + //document.querySelector('#space').classList.toggle('pressed',e.code.toLowerCase()=="space") } if((e.which>=186 && e.which<=192)|| (e.which>=219 && e.which<=222)){ - $("#"+e.code.toLowerCase()).toggleClass("pressed"); + document.querySelector("#"+e.code.toLowerCase()).classList.toggle("pressed"); } if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ if (e.key.toLowerCase()=="meta") { @@ -107,26 +108,26 @@ function handle(e) { } else if (e.code == FIREFOX_RIGHT_COMMAND_STRING) { keyString = CHROME_RIGHT_COMMAND_STRING } - $("#"+keyString.toLowerCase()).toggleClass("pressed"); + document.querySelector("#"+keyString.toLowerCase()).classList.toggle("pressed"); } if(e.key.toLowerCase()=="capslock" && caps==false){ caps= true; - $("#"+e.key.toLowerCase()).toggleClass("pressed"); - $('.letter').toggleClass('uppercase'); + document.querySelector("#"+e.key.toLowerCase()).classList.toggle("pressed"); + document.querySelector('.letter').classList.toggle('uppercase'); } else if(e.key.toLowerCase()=="capslock" && caps==true) { - $("#"+e.key.toLowerCase()).toggleClass("pressed"); - $('.letter').toggleClass('uppercase'); + document.querySelector("#"+e.key.toLowerCase()).classList.toggle("pressed"); + document.querySelector('.letter').classList.toggle('uppercase'); caps=false; } else { if (commandDown) { e.preventDefault(); e.stopPropagation(); - $("#"+e.key.toLowerCase() ).addClass("pressed"); + document.querySelector("#"+e.key.toLowerCase()).classList.add("pressed"); return false; } - $("#"+e.key.toLowerCase() ).addClass("pressed"); + document.querySelector("#"+e.key.toLowerCase()).classList.add("pressed"); } } @@ -155,8 +156,8 @@ function release(e) { document.querySelector("#space").classList.remove("pressed"); } if(e.key.toLowerCase()=="capslock"){ - $("#"+e.key.toLowerCase()).toggleClass("pressed"); - $('.letter').toggleClass('uppercase'); + document.querySelector("#"+e.key.toLowerCase()).classList.toggle("pressed"); + document.querySelector('.letter').classList.toggle('uppercase'); caps=false; } else{ @@ -167,7 +168,7 @@ function release(e) { // May have to be removed. Not being used currently function highlightNextKey(params){ - $("#"+nxt.toLowerCase()).toggleClass("pressed"); + document.querySelector("#"+nxt.toLowerCase()).classList.toggle("pressed"); // // // @@ -188,7 +189,7 @@ function promptKey(key){ // Handling all key types key = key.toLowerCase(); id = key.length == 1 ? key : keyToId[key]; - if (id) $('#' + id).toggleClass('prompt'); + if (id) document.querySelector('#' + id).classList.toggle('prompt'); } /** From 3bbd70bf26f1f3673ba72be8894dc5354b1a7d68 Mon Sep 17 00:00:00 2001 From: Ybrahin Martinez Date: Wed, 7 Oct 2020 23:37:15 -0400 Subject: [PATCH 41/56] Resolving problems --- public/scripts/main.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index f283612..8b2804e 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -90,14 +90,14 @@ function handle(e) { var text1 = e.type + ' key=' + e.key + ' code=' + e.code - + console.log(text1); + if(e.code.toLowerCase()=="space"){ document.querySelector('#space').classList.toggle("pressed"); - //document.querySelector('#space').classList.toggle('pressed',e.code.toLowerCase()=="space") - } + }else if((e.which>=186 && e.which<=192)|| (e.which>=219 && e.which<=222)){ document.querySelector("#"+e.code.toLowerCase()).classList.toggle("pressed"); - } + }else if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ if (e.key.toLowerCase()=="meta") { commandDown = true; @@ -109,7 +109,7 @@ function handle(e) { keyString = CHROME_RIGHT_COMMAND_STRING } document.querySelector("#"+keyString.toLowerCase()).classList.toggle("pressed"); - } + }else if(e.key.toLowerCase()=="capslock" && caps==false){ caps= true; document.querySelector("#"+e.key.toLowerCase()).classList.toggle("pressed"); @@ -121,13 +121,14 @@ function handle(e) { caps=false; } else { + console.log(e); + document.querySelector("#"+e.key.toLowerCase()).classList.add("pressed"); if (commandDown) { e.preventDefault(); e.stopPropagation(); - document.querySelector("#"+e.key.toLowerCase()).classList.add("pressed"); return false; } - document.querySelector("#"+e.key.toLowerCase()).classList.add("pressed"); + //document.querySelector("#"+e.key.toLowerCase()).classList.add("pressed"); } } @@ -136,7 +137,7 @@ function release(e) { if((e.which>=186 && e.which<=192)|| (e.which>=219 && e.which<=222)){ if(document.querySelector("#"+e.code.toLowerCase())) document.querySelector("#"+e.code.toLowerCase()).classList.remove("pressed"); - } + }else if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ if (e.key.toLowerCase()=="meta") { commandDown = false; @@ -150,19 +151,19 @@ function release(e) { if(document.querySelector("#"+keyString.toLowerCase())) document.querySelector("#"+keyString.toLowerCase()).classList.remove("pressed"); - } + }else if(e.code.toLowerCase()=="space"){ if(document.querySelector("#space")) document.querySelector("#space").classList.remove("pressed"); - } + }else if(e.key.toLowerCase()=="capslock"){ document.querySelector("#"+e.key.toLowerCase()).classList.toggle("pressed"); document.querySelector('.letter').classList.toggle('uppercase'); caps=false; } else{ - if(document.querySelector("#"+e.key.toLowerCase() )) - document.querySelector("#"+e.key.toLowerCase() ).classList.remove("pressed"); + if(document.querySelector("#"+e.key.toLowerCase())) + document.querySelector("#"+e.key.toLowerCase()).classList.remove("pressed"); } } From 0ea84ed14f77a568136b4cca6c274d5bf2d94e37 Mon Sep 17 00:00:00 2001 From: Oleksandra Date: Wed, 7 Oct 2020 21:39:31 -0700 Subject: [PATCH 42/56] Add highlight for Fn key in case F1-F12 is pressed. Fixes #29 --- public/scripts/main.js | 15 ++++++++++++++- public/scripts/shortcuts.json | 6 ++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 5dc05dd..a309a87 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -119,6 +119,11 @@ function handle(e) { $('.letter').toggleClass('uppercase'); caps=false; } + // Highlight Fn key if any of F1-F12 is pressed + else if (e.which>=112 && e.which<=123) { + $("#"+e.key.toLowerCase()).addClass("pressed"); + $("#fnc").addClass("pressed"); + } else { if (commandDown) { e.preventDefault(); @@ -176,9 +181,17 @@ function highlightNextKey(params){ function promptKey2(key){ //if($('li[data-keycode="'+key+'"]'[0]).hasClass('prompt')){ if (isShowHint) { - $($('li[data-keycode="'+key+'"]')[0]).addClass("prompt") + $($('li[data-keycode="'+key+'"]')[0]).addClass("prompt"); + // Highlight Fn to be a combination with F1-F12 + if (key>=112 && key <=123) { + $($('li[data-keycode="fn"]')[0]).addClass("prompt"); + } } else { $($('li[data-keycode="'+key+'"]')[0]).removeClass("prompt") + // Remove Fn highlight + if (key>=112 && key <=123) { + $($('li[data-keycode="fn"]')[0]).removeClass("prompt"); + } } //} } diff --git a/public/scripts/shortcuts.json b/public/scripts/shortcuts.json index 5002388..d044b4d 100644 --- a/public/scripts/shortcuts.json +++ b/public/scripts/shortcuts.json @@ -1,4 +1,10 @@ [ + { + "answer": "F2", + "question": "How do you rename a symbol in VSCode?", + "keys": [113], + "shortcutType": "mac vscode" + }, { "answer": "command+x", "question": "How do you cut the selected item and copy it to the clipboard?", From caf0c6708f663b842aa1b2cc3cb4092878d7afc6 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Thu, 8 Oct 2020 17:12:52 -0400 Subject: [PATCH 43/56] fixed all the comments made in review stage --- public/scripts/history.js | 2 +- routes/routes.js | 38 ++++++++++++++++---------------------- 2 files changed, 17 insertions(+), 23 deletions(-) diff --git a/public/scripts/history.js b/public/scripts/history.js index 5d3ea57..f30e5ec 100644 --- a/public/scripts/history.js +++ b/public/scripts/history.js @@ -4,7 +4,7 @@ async function getHistory(questionNo) { let url = new URL(document.URL + 'user/answers/question/' + questionNo); let params = { - userId: 'guest' // TODO: get actual userId + userId: 'guest' } url.search = new URLSearchParams(params).toString(); diff --git a/routes/routes.js b/routes/routes.js index ee29184..6bba9dd 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -1,7 +1,10 @@ const express = require('express'); const router = express.Router(); -const{ User, UserAnswers } = require('../JS/orm'); +const { User, UserAnswers } = require('../JS/orm'); + +const ANSWER_HISTORY_LIMIT = 3; + router.get('/', (req, res) => { res.render('index'); @@ -39,29 +42,20 @@ router.post('/user/answers/question/:questionNumber', (req, res) => { }) router.get('/user/answers/question/:questionNumber', (req, res) => { - let pageSize = 3; // TODO: define it in more stadarized way - - User.findOne({ - where: {id: req.query.userId} - }).then(user => { - - UserAnswers.findAll({ - where: {question_number: req.params.questionNumber, user_id: user.id}, - order: [ - ['created_at', 'DESC'] - ], - limit: pageSize - }).then(userAnswers => { - return res.status(200).json({ - previousTimingMs: userAnswers.map(userAnswer => userAnswer.elapsed_time_ms) - }) - }).catch(error => { - console.log(error); - return res.status(400).json(error.errors) // TODO: handle better error messages + // TODO: When issue #74 be done, the userId should be handled differently from req object + UserAnswers.findAll({ + where: {question_number: req.params.questionNumber, user_id: req.query.userId}, + order: [ + ['created_at', 'DESC'] + ], + limit: ANSWER_HISTORY_LIMIT + }).then(userAnswers => { + return res.json({ + previousTimingMs: userAnswers.map(userAnswer => userAnswer.elapsed_time_ms) }) }).catch(error => { - console.log(error); - return res.status(400).json({message: "User doesn't exists."}) // TODO: handle better error messages + console.log(error); + return res.status(500).json(error.errors) // TODO: handle better error messages }) }) From 7878e216ef8b47283094f3649dfc53990ebfb360 Mon Sep 17 00:00:00 2001 From: Oleksandra Date: Thu, 8 Oct 2020 15:06:24 -0700 Subject: [PATCH 44/56] Fixes #29. Add Fn un-highlight on release F1-12 --- public/scripts/main.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index a309a87..46258a0 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -109,6 +109,11 @@ function handle(e) { } $("#"+keyString.toLowerCase()).toggleClass("pressed"); } + // Highlight Fn key if any of F1-F12 is pressed + if (e.which>=112 && e.which<=123) { + $("#"+e.key.toLowerCase()).addClass("pressed"); + $("#fnc").addClass("pressed"); + } if(e.key.toLowerCase()=="capslock" && caps==false){ caps= true; $("#"+e.key.toLowerCase()).toggleClass("pressed"); @@ -119,11 +124,6 @@ function handle(e) { $('.letter').toggleClass('uppercase'); caps=false; } - // Highlight Fn key if any of F1-F12 is pressed - else if (e.which>=112 && e.which<=123) { - $("#"+e.key.toLowerCase()).addClass("pressed"); - $("#fnc").addClass("pressed"); - } else { if (commandDown) { e.preventDefault(); @@ -159,6 +159,11 @@ function release(e) { if(document.querySelector("#space")) document.querySelector("#space").classList.remove("pressed"); } + // Uhighlight Fn key if any of F1-F12 is pressed + if (e.which>=112 && e.which<=123) { + $("#"+e.key.toLowerCase()).removeClass("pressed"); + $("#fnc").removeClass("pressed"); + } if(e.key.toLowerCase()=="capslock"){ $("#"+e.key.toLowerCase()).toggleClass("pressed"); $('.letter').toggleClass('uppercase'); From 0b014b36f3259e9fe80cb1fb4ea269a1130f0d8e Mon Sep 17 00:00:00 2001 From: Oleksandra Date: Thu, 8 Oct 2020 16:55:43 -0700 Subject: [PATCH 45/56] Fixes #29. Change jQuery to native DOM functions. Move macVSCode shortcut to the end. --- public/scripts/main.js | 12 ++++++------ public/scripts/shortcuts.json | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 46258a0..f191256 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -111,8 +111,8 @@ function handle(e) { } // Highlight Fn key if any of F1-F12 is pressed if (e.which>=112 && e.which<=123) { - $("#"+e.key.toLowerCase()).addClass("pressed"); - $("#fnc").addClass("pressed"); + document.querySelector("#"+e.key.toLowerCase()).classList.add("pressed"); + document.querySelector("#fnc").classList.add("pressed"); } if(e.key.toLowerCase()=="capslock" && caps==false){ caps= true; @@ -161,8 +161,8 @@ function release(e) { } // Uhighlight Fn key if any of F1-F12 is pressed if (e.which>=112 && e.which<=123) { - $("#"+e.key.toLowerCase()).removeClass("pressed"); - $("#fnc").removeClass("pressed"); + document.querySelector("#"+e.key.toLowerCase()).classList.remove("pressed"); + document.querySelector("#fnc").classList.remove("pressed"); } if(e.key.toLowerCase()=="capslock"){ $("#"+e.key.toLowerCase()).toggleClass("pressed"); @@ -189,13 +189,13 @@ function promptKey2(key){ $($('li[data-keycode="'+key+'"]')[0]).addClass("prompt"); // Highlight Fn to be a combination with F1-F12 if (key>=112 && key <=123) { - $($('li[data-keycode="fn"]')[0]).addClass("prompt"); + document.querySelector("#fnc").classList.add("prompt"); } } else { $($('li[data-keycode="'+key+'"]')[0]).removeClass("prompt") // Remove Fn highlight if (key>=112 && key <=123) { - $($('li[data-keycode="fn"]')[0]).removeClass("prompt"); + document.querySelector("#fnc").classList.remove("prompt"); } } //} diff --git a/public/scripts/shortcuts.json b/public/scripts/shortcuts.json index d044b4d..3643082 100644 --- a/public/scripts/shortcuts.json +++ b/public/scripts/shortcuts.json @@ -1,10 +1,4 @@ [ - { - "answer": "F2", - "question": "How do you rename a symbol in VSCode?", - "keys": [113], - "shortcutType": "mac vscode" - }, { "answer": "command+x", "question": "How do you cut the selected item and copy it to the clipboard?", @@ -196,5 +190,11 @@ "question": "How do you open preferences for the front app?", "keys": [91, 188], "shortcutType": "mac" + }, + { + "answer": "F2", + "question": "How do you rename a symbol in VSCode?", + "keys": [113], + "shortcutType": "mac vscode" } ] From 256de3fc9aaa38b4f2619c2a37e3372cf45ab074 Mon Sep 17 00:00:00 2001 From: Josseline Perdomo Date: Thu, 8 Oct 2020 20:01:09 -0400 Subject: [PATCH 46/56] added mock userId on the server --- public/scripts/history.js | 4 ---- routes/routes.js | 6 ++++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/public/scripts/history.js b/public/scripts/history.js index f30e5ec..e3516e0 100644 --- a/public/scripts/history.js +++ b/public/scripts/history.js @@ -3,10 +3,6 @@ // returns an array with timing data for a given question number async function getHistory(questionNo) { let url = new URL(document.URL + 'user/answers/question/' + questionNo); - let params = { - userId: 'guest' - } - url.search = new URLSearchParams(params).toString(); try{ let response = await fetch(url); diff --git a/routes/routes.js b/routes/routes.js index 6bba9dd..71be56a 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -42,9 +42,11 @@ router.post('/user/answers/question/:questionNumber', (req, res) => { }) router.get('/user/answers/question/:questionNumber', (req, res) => { - // TODO: When issue #74 be done, the userId should be handled differently from req object + // TODO: When issue #74 be done, the userId should be handled from req object + let userId = 'guest'; + UserAnswers.findAll({ - where: {question_number: req.params.questionNumber, user_id: req.query.userId}, + where: {question_number: req.params.questionNumber, user_id: userId}, order: [ ['created_at', 'DESC'] ], From a395c60845735dd3470126217f61abf8d92f3a86 Mon Sep 17 00:00:00 2001 From: Nidhish <55269918+nidhishs@users.noreply.github.com> Date: Sat, 10 Oct 2020 12:09:10 +0200 Subject: [PATCH 47/56] Added favicon Used serve-icon middleware to serve favicon. --- app.js | 2 ++ package-lock.json | 57 +++++++++++++++++++++++++++----------- package.json | 3 +- public/images/favicon.ico | Bin 0 -> 22382 bytes 4 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 public/images/favicon.ico diff --git a/app.js b/app.js index ecb5b18..b8fda39 100644 --- a/app.js +++ b/app.js @@ -5,6 +5,7 @@ const bodyParser = require("body-parser"); const { auth } = require('express-openid-connect'); const { connectToDb } = require("./JS/orm"); const { authConfig } = require("./JS/auth0"); +const favicon = require('serve-favicon'); const app = express(); app.use(morgan("dev")); //morgan gives us useful logging @@ -16,6 +17,7 @@ app.set("views", path.join(__dirname, "views")); app.use(express.static("public")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); +app.use(favicon(__dirname + '/public/images/favicon.ico')); if (authConfig) { app.use(auth(authConfig)); // auth router attaches /login, /logout, and /callback routes to the baseURL diff --git a/package-lock.json b/package-lock.json index 5298b6e..f04ff08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1031,6 +1031,7 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "optional": true, "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -1246,6 +1247,22 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" + }, + "ecstatic": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", + "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "requires": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + } + }, + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" } } }, @@ -2091,22 +2108,6 @@ } } }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" - } - } - }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -2688,6 +2689,30 @@ "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==" }, + "serve-favicon": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", + "integrity": "sha1-k10kDN/g9YBTB/3+ln2IlCosvPA=", + "requires": { + "etag": "~1.8.1", + "fresh": "0.5.2", + "ms": "2.1.1", + "parseurl": "~1.3.2", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + } + } + }, "serve-static": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", diff --git a/package.json b/package.json index 9b2e74f..8fc414d 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,8 @@ "ecstatic": "^4.1.4", "ejs": "^3.0.1", "express": "^4.17.1", - "http-server": "^0.12.3", "express-openid-connect": "^2.0.0", + "http-server": "^0.12.3", "morgan": "^1.9.1", "mysql": "^2.17.1", "path": "^0.12.7", @@ -33,6 +33,7 @@ "pg-hstore": "^2.3.3", "request": "^2.88.0", "sequelize": "^6.3.5", + "serve-favicon": "^2.5.0", "sqlite3": "^5.0.0" }, "devDependencies": { diff --git a/public/images/favicon.ico b/public/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..cc05fe5e2b856b5f93cada4e77f63ceafdd1b7eb GIT binary patch literal 22382 zcmeI4O>9(E6vuBZp%P7sQA`LVc3A@pS4PN?Hbxgxb)kFL#z066x6cVGx6vqGW%{}eqb?&_RdYw+6ll(b%?!D*Zf9|<= z-g`6Dxgj^~CMTWbm>YlCxd)wdV`KIAZ?1Rl8TGA~Wc=AR&aHjgxpB>riYp8BC$CB8 zc5bbs-jUD0rw)%hVMw?~C<(iTL&B^uCtMfig_;L#`WRylbI~aY*uYjk!S={1@p%yM zlyFcuEnF2suEse_qJu6ru!T)*Cw_VqcGqTnJhw@X3;Tq#!rwv`zjnv5iEVt~3!h!b z->Ct73)CgCydwN6+!Wg7)$V+J;0vGlUe>)Ke^%#rtG!paAhgS&SM%{r48)TAzVJTC zcS$%Q%nQBZ(y1L{AeNGlTP?^o`CTXM5-tm!#+#QOF%cUvcDk*X=wZu)8si+!<813y zPKb>dd$J#7$GC4)`>=3B=vAzF*&#+^CFYLL1k?3)j!5PeZ(eqZx#Jvo{?rk<%qzyc z?Gk&k7nW@7CLNyp?UL-JL8$py9*G?eaB0GLafo>yoTV%Itc!6@_rn1$nP-8`k=!9% z64JH?^*vnR)HDZvoO=weCkB;kEN(a@_fLz}zS#2I$q(0)gS_Ws{NV(*hBe^(@0UC; z#B2n*`hz|W$AubD+tzD3wj4aJcKTZ9L-oBROb6Jn_DR9=NSnS`f2i9{J7z!DANqm=TxtQ} z3TNZbHDWkU`#HwLm!FSqn_KpM*jdsa>UPua#;@0fi^Xgb&cw|%0nb>i-{flN4`;ZS zgewjBTm7@fhFHDD`c1D}8M7bj5B)W&f7TezaNjM=3%2e>k#L6lp#pNZHHJIiH`)78 zTK!LJ+z_j`e)U^i$W~*h1$^!MxUkRKU7vsQ<9zPSCi{}Up7e*GDQ(!aSdeqVbs_At zb`ki)J$Ck4{j+9e2WX&sxMn#WQ=<_=l^!&{jpl|5~~5L|7q2Uq175Y z>Fcpy^DSOv?E0tX>wjR+KgI6^IKl;R4ul^Ij04Vcn-fa7&qc;o{Q0lAyX6n}tm_|g zYUo!zx9iv9MK-H{`>jz}6Gdus{af_=pOSKLRYfi2v zn?C;#N9TFge2&;tjm}tNxMdFWgxvaX2_o{w$I$5fKdmvi6XQX_VmFzb|9*T4htOSY zPTu`t46(M4p%H&L!yWJ}F!ua2R>NiK7-Dns?l=F{}u2r?DwBR4yb|it9T#4ZQ;95c-zbG0rtXP;fAo<&OkW9ZDHRV zcawgMYl0KPYU2;5Wrlsdkes&0j`~4I72y(DX?esO#Al3vN;1aF-NF5aN_m7qf zpRYpx{x!7^_ziL4e*fGc2Zj3mduktWcCZ(?XI#l=BC!!;@|$l-qtUg*matCXEG^9c ze+d)kbHIHUYtD@#%ld-> z5;sZdbTXVw&~P%LiX5rcD#+nvdZNHv=jv)wlvQ36CjY6wzb`Q(Lnf>B{*g*u4yR?g z-alk==GttnHaj{qRF}THKB>{ans?^|vlq)I8_fy(>hnhZ{Lyka)~G%7GWKibnYx_u z3JdX8>Pky^RqOpDmIsrTC(E13WI0%ny53^mD|Bcbsz|L%Vn_>_C{8S{qpj=0I%|T4 z*-2x-VJlY+*AR zgN;c(BK#t>YQNQa*u?gd7_3i{81wLLF=Bg39=!j}l3xfmH!q0~d?lrT6ov)rBrl(7 zyZFLqvKErtg>LFRZ9nThzVK<>*{fMPy&lIWIoK*x1@_6;!cpOvK#bsc(59c?4>UtF zU2Nk6U--l~=Ot&>U&3R;h;Wzina90BoBlg8&`cNG_`nxF@qI)fw>(GxR`^)>RJh_n z9M+~Eet^6*YB$m)k2V({_{Jx`*^{mM4`XSiO)RXH`8=aGfGa-n&1VpY+)oPfS_)Z-sL>CyPJ6^Ym}A#MU3*dFDS{BU=lrf6ITm{;W=k znYuR)-L_c^_7-b=L$LY__aFB}X9e~L^Qc|)@ZE`jbdAp^YO`lU|M=b`*!lCQ+SDj( zLd`Zii^AN-+UfI(?;b4wcK&QtpPj#7sZ9=y|53GxpS1wtS=>q+-SDi&Ui$pyGoYWJ zKYRvm7vM)tEC=v~Pke*EU4L*9#_bh)pmaHS6OFMjEykYUOyincV2g+#$FTt5Muj_G3IPU2VJ!R zy6+1yy>vfw(Lr~ufX(!rtoP`kJ0<+yfj&Cuz9aD2R~Go3{YaqidEo^Q+VnB@rLbQ> zhrY|g4+4APdx7)ebAftf9MGn(B5>Wr=k1RIx?JnwH}sDm>>$H7Yxt^wEv^U9HGN_t zwzN*DPdoI5uEqa>+QdeT`2Nnzu#MmMgx3W)qYJ-p1oVjQZ6WQ`xG`zfKD n^;;|bZtBNLzvKGtcK_Hu>~#NDN1Uq+>+jySaT+lf9d!Q#?#4l2 literal 0 HcmV?d00001 From 1b78bae247a0430583f2239945a1b0976fb42f75 Mon Sep 17 00:00:00 2001 From: Oleksandra <4979096+Karska-dev@users.noreply.github.com> Date: Tue, 13 Oct 2020 07:50:28 -0700 Subject: [PATCH 48/56] Fixes #138. Add clear prompt for all hint keys (#139) --- public/scripts/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index f191256..badaf3d 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -284,7 +284,7 @@ function clearIncorrectIndication() { function clearPromptKeys() { if(document.querySelector('.prompt')) - document.querySelector('.prompt').classList.remove('prompt'); + document.querySelectorAll('.prompt').forEach(key => key.classList.remove('prompt')); }; From 11d0c5b767e70ce55858ca2fe36020e2772abb45 Mon Sep 17 00:00:00 2001 From: Ybrahin Martinez Date: Wed, 14 Oct 2020 12:21:40 -0400 Subject: [PATCH 49/56] Resolve problem with keys that are not used, remove a comment --- public/scripts/main.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/public/scripts/main.js b/public/scripts/main.js index 2be8be6..ab5c39a 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -112,7 +112,6 @@ function handle(e) { // Highlught Numpad keys if(e.which>=96 && e.which<=105){ - console.log("teclado numerico"); document.querySelector(`li[id="${e.key}"]`).classList.add('pressed'); return true; }else @@ -128,14 +127,17 @@ function handle(e) { document.querySelector("#"+e.key.toLowerCase()).classList.add("pressed"); return false; } - - document.querySelector(`li[data-keycode="${e.keyCode}"]`).classList.add('pressed'); + if(document.querySelector(`li[data-keycode="${e.keyCode}"]`)) + document.querySelector(`li[data-keycode="${e.keyCode}"]`).classList.add('pressed'); } // Function called on KeyUp to reset the key by removing class = 'pressed' function release(e) { + if(e.key.toLowerCase()=="capslock") + return true; + if(e.key.toLowerCase()=="alt" || e.key.toLowerCase()=="shift" || e.key.toLowerCase()=="meta"){ if (e.key.toLowerCase()=="meta") { commandDown = false; @@ -163,7 +165,7 @@ function release(e) { if(document.querySelector("#fnc").classList.contains("pressed")) document.querySelector("#fnc").classList.remove("pressed"); } - if(document.querySelector(`li[data-keycode="${e.keyCode}"]`).classList.contains('pressed')) + if(document.querySelector(`li[data-keycode="${e.keyCode}"]`) && document.querySelector(`li[data-keycode="${e.keyCode}"]`).classList.contains('pressed')) document.querySelector(`li[data-keycode="${e.keyCode}"]`).classList.remove('pressed'); } From fbf911e436a2e3e3a818f728910291ece5813d5b Mon Sep 17 00:00:00 2001 From: Bill DePhillips <355438+vegetabill@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:14:46 -0700 Subject: [PATCH 50/56] App can use Auth0 or local dev auth (#133) * Fixes #74 - fake login/logout for local dev - refactor auth setup so it is the same for the rest of the code regardless if it's fake dev or Auth0 - use express-session with sequelize store to handle sessions (they will persist dev reload) - add dummy login state message to bottom of index page so dev can use login/logout before buttons are added * make .env.example a little more user-friendly * add .git.local ignore so it can be used to switch between Auth0 and local dev without accidentally checking it in * Fully integrate Auth0 and local dev - Auth create user upon login or root request - Protect all /user API routes to need a valid signed-in user or they will respond with 401 - fix ORM data models so they have default values and work correctly with postgres * fix comments --- .env.example | 4 +- .gitignore | 1 + JS/auth-dev.js | 46 ++ JS/auth-setup.js | 61 ++ JS/auth0.js | 36 +- JS/config.js | 5 +- JS/orm.js | 42 +- JS/router.js | 1 - app.js | 17 +- package-lock.json | 1346 +++++++++++++++++++++++++++++++-------------- package.json | 2 + routes/routes.js | 97 ++-- views/index.ejs | 7 + 13 files changed, 1132 insertions(+), 533 deletions(-) create mode 100644 JS/auth-dev.js create mode 100644 JS/auth-setup.js delete mode 100644 JS/router.js diff --git a/.env.example b/.env.example index 910ce35..141015c 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -DB_URL=dev mode defaults to sqlite (so this is not needed) +#DB_URL=dev mode defaults to sqlite (so this is not needed) AUTH0_CLIENT_ID=YOUR_CLIENT_ID AUTH0_SECRET=YOUR_CLIENT_SECRET -AUTH0_ISSUER_BASE_URL=APPLICATION_TENANT_DOMAIN_URL +AUTH0_ISSUER_BASE_URL=https://.auth0.com diff --git a/.gitignore b/.gitignore index a954538..156f227 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store .env +.env.local node_modules/ dev-db.sqlite \ No newline at end of file diff --git a/JS/auth-dev.js b/JS/auth-dev.js new file mode 100644 index 0000000..11dc6ac --- /dev/null +++ b/JS/auth-dev.js @@ -0,0 +1,46 @@ +/** + * Simple cookie session auth for local development when not testing with Auth0. + * Uses Sequelize to store the sessions using an adapter. + * + * - `/login` will automatically sign you in as a current $USER + * (this user will be created if it does not exist) + * - `/logout` will sign you out + */ + +const { User, sequelize } = require("./orm"); +const session = require("express-session"); +const SequelizeStore = require("connect-session-sequelize")(session.Store); + +const userIdLoader = (req) => req.session.userId; + +const setup = (app) => { + app.use( + session({ + secret: "techtonica", + store: new SequelizeStore({ + db: sequelize, + tableName: "sessions", + expiration: 1000 * 60 * 30, //30min + }), + unset: "destroy", + resave: false, + saveUninitialized: true, + }) + ); + + app.get("/login", async (req, res) => { + const userId = process.env.USER || "local"; + await User.findOrCreate({ + where: { id: userId }, + }); + req.session.userId = userId; + res.redirect("/"); + }); + + app.get("/logout", (req, res) => { + req.session = null; + res.redirect("/"); + }); +}; + +module.exports = { setup, userIdLoader }; diff --git a/JS/auth-setup.js b/JS/auth-setup.js new file mode 100644 index 0000000..79b7947 --- /dev/null +++ b/JS/auth-setup.js @@ -0,0 +1,61 @@ +const { auth } = require("express-openid-connect"); +const Auth0 = require("./auth0"); +const { User } = require("./orm"); +/** + * Retrieves the currently signed-in user id, if signed-in, + * from the Express Response object. + * + * This mechanism is independent if the app is using Auth0 or not. + * + * @param {*} response Express Response object + */ +const getCurrentUserId = (response) => response.locals.currentUserId; + +const findCurrentUserFrom = (loadUserIdFunc) => { + return (req, res, next) => { + const userId = loadUserIdFunc(req); + res.locals.currentUserId = userId; + next(); + }; +}; + +/** + * Ensures user record exists for a signed-in user. + * Needed for incoming Auth0 users. + */ +const autoCreateSignedInUser = async (_, res, next) => { + const userId = getCurrentUserId(res); + if (userId) { + const [user, created] = await User.findOrCreate({ + where: { id: userId }, + }); + if (created) { + console.debug(`auto-created newly signed-in user: ${user.id}`); + } + } + next(); +}; + +const routeRequiresSignedIn = (_, res, next) => { + if (!getCurrentUserId(res)) { + return res.sendStatus(401); + } + next(); +}; + +const setupAuth = (app) => { + if (Auth0.authConfig) { + console.debug("Using Auth0 auth"); + // auth router attaches /login, /logout, and /callback routes to the baseURL + app.use(auth(Auth0.authConfig)); + app.use(findCurrentUserFrom(Auth0.userIdLoader)); + app.use("/", autoCreateSignedInUser); + } else { + console.debug("Using dev auth"); + const AuthDev = require("./auth-dev"); + AuthDev.setup(app); + app.use(findCurrentUserFrom(AuthDev.userIdLoader)); + } +}; + +module.exports = { setupAuth, routeRequiresSignedIn, getCurrentUserId }; diff --git a/JS/auth0.js b/JS/auth0.js index 553fb11..7b00927 100644 --- a/JS/auth0.js +++ b/JS/auth0.js @@ -1,26 +1,22 @@ const { AUTH0_SECRET, AUTH0_CLIENT_ID, AUTH0_ISSUER_BASE_URL } = process.env; -const port = process.env.port || 3000; -let authConfig = undefined; +const { port } = require("./config"); -const isValidUrl = () => { - try { - new URL(AUTH0_ISSUER_BASE_URL); - } catch (_) { - return false; - } -} +let authConfig = false; -if (AUTH0_SECRET != undefined && AUTH0_CLIENT_ID != undefined && isValidUrl) { - authConfig = { - authRequired: false, - auth0Logout: true, - issuerBaseURL: AUTH0_ISSUER_BASE_URL, - baseURL: 'http://localhost:'.concat(port), - clientID: AUTH0_CLIENT_ID, - secret: AUTH0_SECRET, - }; -} +if (AUTH0_SECRET && AUTH0_CLIENT_ID) { + authConfig = { + authRequired: false, + auth0Logout: true, + issuerBaseURL: AUTH0_ISSUER_BASE_URL, + baseURL: "http://localhost:".concat(port), + clientID: AUTH0_CLIENT_ID, + secret: AUTH0_SECRET, + }; +} + +const userIdLoader = (req) => req.oidc.user && req.oidc.user.sub; module.exports = { - authConfig + authConfig, + userIdLoader, }; diff --git a/JS/config.js b/JS/config.js index 13a5dd2..91c92a1 100644 --- a/JS/config.js +++ b/JS/config.js @@ -1,7 +1,7 @@ -require("dotenv").config(); - const { DB_URL, NODE_ENV } = process.env; +const port = process.env.port || 3000; + const isProduction = () => NODE_ENV === "production"; const isDevelopment = () => NODE_ENV === "development"; @@ -15,5 +15,6 @@ const getDefaultDbUrl = () => { module.exports = { isProduction, isDevelopment, + port, DB_URL: DB_URL || getDefaultDbUrl(), }; diff --git a/JS/orm.js b/JS/orm.js index 784dabf..1ede885 100644 --- a/JS/orm.js +++ b/JS/orm.js @@ -8,8 +8,10 @@ const Model = Sequelize.Model; class User extends Model {} User.init( { - q_number: Sequelize.STRING, - last_login: Sequelize.DATE, + last_login: { + type: Sequelize.DATE, + defaultValue: Sequelize.NOW, + }, id: { type: Sequelize.STRING, primaryKey: true, @@ -22,38 +24,35 @@ User.init( updatedAt: "updated_at", } ); -class UserAnswers extends Model{} +class UserAnswers extends Model {} UserAnswers.init( { - id:{ - primaryKey : true, - type: Sequelize.INTEGER, - }, - user_id:{ + user_id: { type: Sequelize.STRING, - allowNull: false + allowNull: false, }, - question_number:{ + question_number: { type: Sequelize.INTEGER, - allowNull: false + allowNull: false, }, - is_correct:{ + is_correct: { type: Sequelize.BOOLEAN, - allowNull: false + allowNull: false, }, - elapsed_time_ms:{ + elapsed_time_ms: { type: Sequelize.INTEGER, - allowNull: false + allowNull: false, }, - },{ + }, + { sequelize, modelName: "user_answers", - createdAt: 'created_at', - updatedAt: false + createdAt: "created_at", + updatedAt: false, } ); -User.hasMany(UserAnswers, {foreignKey: 'user_id'}); -UserAnswers.belongsTo(User,{foreignKey: 'user_id'}); +User.hasMany(UserAnswers, { foreignKey: "user_id" }); +UserAnswers.belongsTo(User, { foreignKey: "user_id" }); const connectToDb = async () => { await sequelize.authenticate(); await sequelize.sync(); @@ -62,5 +61,6 @@ const connectToDb = async () => { module.exports = { User, connectToDb, - UserAnswers + UserAnswers, + sequelize, }; diff --git a/JS/router.js b/JS/router.js deleted file mode 100644 index efd6259..0000000 --- a/JS/router.js +++ /dev/null @@ -1 +0,0 @@ -import { User, UserAnswers } from 'orm.js'; \ No newline at end of file diff --git a/app.js b/app.js index b8fda39..aeac87b 100644 --- a/app.js +++ b/app.js @@ -1,11 +1,12 @@ +require("dotenv").config(); const path = require("path"); const morgan = require("morgan"); const express = require("express"); const bodyParser = require("body-parser"); -const { auth } = require('express-openid-connect'); +const { setupAuth } = require("./JS/auth-setup"); const { connectToDb } = require("./JS/orm"); -const { authConfig } = require("./JS/auth0"); -const favicon = require('serve-favicon'); +const { port } = require("./JS/config"); +const favicon = require("serve-favicon"); const app = express(); app.use(morgan("dev")); //morgan gives us useful logging @@ -17,22 +18,18 @@ app.set("views", path.join(__dirname, "views")); app.use(express.static("public")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); -app.use(favicon(__dirname + '/public/images/favicon.ico')); - -if (authConfig) { - app.use(auth(authConfig)); // auth router attaches /login, /logout, and /callback routes to the baseURL -} +app.use(favicon(__dirname + "/public/images/favicon.ico")); +setupAuth(app); const routes = require("./routes/routes.js"); app.use("/", routes); -app.use((req, res) => { +app.use((_, res) => { res.status(404).render("not_found"); }); const startServer = async () => { await connectToDb(); - const port = process.env.port || 3000; app.listen(port, () => { console.log(`Listening on http://localhost:${port} :-D`); }); diff --git a/package-lock.json b/package-lock.json index f04ff08..4d0dd89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,18 +53,16 @@ "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" }, "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz", + "integrity": "sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ==" }, "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", + "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", "requires": { - "defer-to-connect": "^1.0.1" + "defer-to-connect": "^2.0.0" } }, "@types/cacheable-request": { @@ -78,12 +76,6 @@ "@types/responselike": "*" } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, "@types/http-cache-semantics": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz", @@ -98,9 +90,9 @@ } }, "@types/node": { - "version": "14.6.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.4.tgz", - "integrity": "sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==" + "version": "14.14.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.2.tgz", + "integrity": "sha512-jeYJU2kl7hL9U5xuI/BhKPZ4vqGM/OmK6whiFAXVhlstzZhVamWhDSmHyGLIp+RVyuF9/d0dqr2P85aFj4BvJg==" }, "@types/responselike": { "version": "1.0.0", @@ -134,9 +126,9 @@ } }, "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -153,6 +145,18 @@ "string-width": "^3.0.0" }, "dependencies": { + "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 + }, + "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 + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -163,14 +167,22 @@ "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } } } }, "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 + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "ansi-styles": { "version": "3.2.1", @@ -209,6 +221,12 @@ "readable-stream": "^2.0.6" } }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -237,6 +255,15 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -258,12 +285,9 @@ "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" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -326,13 +350,18 @@ "widest-line": "^3.1.0" }, "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -361,12 +390,44 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -412,35 +473,17 @@ "integrity": "sha512-W+JBqF9SWe18A72XFzN/V/CULFzPm7sBXzzR6ekkE+3tLG72wFZrBiBZhrZuDoYexop4PHJVdFAKb/Nj9+tm9w==" }, "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", + "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", "requires": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", + "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } + "responselike": "^2.0.0" } }, "camelcase": { @@ -475,9 +518,9 @@ "integrity": "sha512-6dVyOOYjpfFcL1Y4qChrAoQLRHvj2ziyhcm0QJlhOcAhykL/k1kTUPbeo+87MNRTRdk2OIIsIXbuF3x2wi5EXg==" }, "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -487,7 +530,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" + "readdirp": "~3.5.0" } }, "chownr": { @@ -575,6 +618,33 @@ "xdg-basedir": "^4.0.0" } }, + "connect-session-sequelize": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/connect-session-sequelize/-/connect-session-sequelize-7.0.4.tgz", + "integrity": "sha512-PSuupsQ50I8eLJOH/pcBZ7r4V8Z7Hz3TrNZo5G2BXc6NVErbf9bRf5780ypLePWVKAxkly+0U1MVnKjS36JULQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "deep-equal": "^2.0.3" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -667,12 +737,48 @@ } }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } + } + }, + "deep-equal": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.4.tgz", + "integrity": "sha512-BUfaXrVoCfgkOQY/b09QdO9L3XNoF2XH0A3aY9IQwQL/ZjLOe8FQgCNVl1wiolhsFo8kFdO9zdPViCPbmaJA5w==", "dev": true, "requires": { - "mimic-response": "^1.0.0" + "es-abstract": "^1.18.0-next.1", + "es-get-iterator": "^1.1.0", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.1.1", + "isarray": "^2.0.5", + "object-is": "^1.1.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } } }, "deep-extend": { @@ -681,10 +787,18 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, "defer-to-connect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz", + "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==" + }, + "define-properties": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true + "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" + } }, "delayed-stream": { "version": "1.0.0", @@ -756,13 +870,6 @@ "minimist": "^1.1.0", "on-finished": "^2.3.0", "url-join": "^4.0.0" - }, - "dependencies": { - "mime": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", - "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" - } } }, "ee-first": { @@ -797,6 +904,79 @@ "once": "^1.4.0" } }, + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "dev": true, + "requires": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escape-goat": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", @@ -918,11 +1098,36 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + } + } + }, + "express-session": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", + "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", + "dev": true, + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.0", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true }, - "url-join": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", - "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true } } }, @@ -982,6 +1187,12 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -1039,6 +1250,12 @@ "rimraf": "2" } }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, "futoin-hkdf": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.3.2.tgz", @@ -1057,46 +1274,12 @@ "string-width": "^1.0.1", "strip-ansi": "^3.0.1", "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } } }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "requires": { "pump": "^3.0.0" } @@ -1141,22 +1324,21 @@ } }, "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.0.tgz", + "integrity": "sha512-k9noyoIIY9EejuhaBNLyZ31D5328LeqnyPNXJQb2XlJZcKakLqN5m6O/ikhq/0lw56kUYS54fVm+D1x57YC9oQ==", + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.1", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" } }, "graceful-fs": { @@ -1178,11 +1360,26 @@ "har-schema": "^2.0.0" } }, + "has": { + "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" + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -1243,11 +1440,6 @@ "union": "~0.5.0" }, "dependencies": { - "basic-auth": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", - "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" - }, "ecstatic": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", @@ -1259,6 +1451,11 @@ "url-join": "^2.0.5" } }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, "url-join": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", @@ -1353,6 +1550,18 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, + "is-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz", + "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==", + "dev": true + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -1362,6 +1571,18 @@ "binary-extensions": "^2.0.0" } }, + "is-boolean-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==", + "dev": true + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, "is-ci": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", @@ -1371,6 +1592,12 @@ "ci-info": "^2.0.0" } }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -1378,9 +1605,12 @@ "dev": true }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-glob": { "version": "4.0.1", @@ -1401,6 +1631,18 @@ "is-path-inside": "^3.0.1" } }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, "is-npm": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", @@ -1413,6 +1655,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, "is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", @@ -1425,13 +1673,88 @@ "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", "dev": true }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } }, - "is-yarn-global": { - "version": "0.3.0", + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typed-array": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz", + "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.0", + "es-abstract": "^1.17.4", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true + }, + "is-weakset": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", + "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==", + "dev": true + }, + "is-yarn-global": { + "version": "0.3.0", "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true @@ -1476,10 +1799,9 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, "json-schema": { "version": "0.2.3", @@ -1508,12 +1830,11 @@ } }, "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", + "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", "requires": { - "json-buffer": "3.0.0" + "json-buffer": "3.0.1" } }, "latest-version": { @@ -1531,10 +1852,9 @@ "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" }, "lru-cache": { "version": "6.0.0", @@ -1599,9 +1919,9 @@ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==" }, "mime-db": { "version": "1.44.0", @@ -1672,9 +1992,9 @@ } }, "moment": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz", - "integrity": "sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA==" + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" }, "moment-timezone": { "version": "0.5.31", @@ -1696,6 +2016,14 @@ "on-headers": "~1.0.2" }, "dependencies": { + "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" + } + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1774,15 +2102,6 @@ "which": "1" }, "dependencies": { - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "optional": true, - "requires": { - "abbrev": "1" - } - }, "semver": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", @@ -1844,9 +2163,9 @@ } }, "nodemon": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz", - "integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz", + "integrity": "sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==", "dev": true, "requires": { "chokidar": "^3.2.2", @@ -1857,8 +2176,8 @@ "semver": "^5.7.1", "supports-color": "^5.5.0", "touch": "^3.1.0", - "undefsafe": "^2.0.2", - "update-notifier": "^4.0.0" + "undefsafe": "^2.0.3", + "update-notifier": "^4.1.0" }, "dependencies": { "debug": { @@ -1885,10 +2204,10 @@ } }, "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "optional": true, "requires": { "abbrev": "1" } @@ -1958,6 +2277,40 @@ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz", "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==" }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-is": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz", + "integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "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 + }, + "object.assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, "oidc-token-hash": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.0.tgz", @@ -1990,9 +2343,9 @@ "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" }, "openid-client": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-4.1.1.tgz", - "integrity": "sha512-/qch3I3v8UtO0A7wVgyXJJjGX/knR8bv06DQpLuKQqLG5u4AHcgusGuVKPKAcneLZvHKbKovF2+3e2ngXyuudA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-4.2.0.tgz", + "integrity": "sha512-1S7pLF4xkWkX3l0Gpt69jlXLiO+oRUBjMcc9MZCyoyzz5+KnHUs2D5xMx4RIH/g9QmAwob1zg7mKZLdvOB52Bw==", "requires": { "base64url": "^3.0.1", "got": "^11.6.2", @@ -2002,110 +2355,6 @@ "object-hash": "^2.0.1", "oidc-token-hash": "^5.0.0", "p-any": "^3.0.0" - }, - "dependencies": { - "@sindresorhus/is": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-3.1.2.tgz", - "integrity": "sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ==" - }, - "@szmarczak/http-timer": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", - "integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==", - "requires": { - "defer-to-connect": "^2.0.0" - } - }, - "cacheable-request": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.1.tgz", - "integrity": "sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==", - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^2.0.0" - } - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "requires": { - "mimic-response": "^3.1.0" - } - }, - "defer-to-connect": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.0.tgz", - "integrity": "sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==" - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "got": { - "version": "11.7.0", - "resolved": "https://registry.npmjs.org/got/-/got-11.7.0.tgz", - "integrity": "sha512-7en2XwH2MEqOsrK0xaKhbWibBoZqy+f1RSUoIeF1BLcnf+pyQdDsljWMfmOh+QKJwuvDIiKx38GtPh5wFdGGjg==", - "requires": { - "@sindresorhus/is": "^3.1.1", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.1", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - } - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "keyv": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", - "integrity": "sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==", - "requires": { - "json-buffer": "3.0.1" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - }, - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" - }, - "p-cancelable": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", - "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" - }, - "responselike": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", - "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", - "requires": { - "lowercase-keys": "^2.0.0" - } - } } }, "os-homedir": { @@ -2134,20 +2383,12 @@ "requires": { "p-cancelable": "^2.0.0", "p-some": "^5.0.0" - }, - "dependencies": { - "p-cancelable": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", - "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" - } } }, "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", + "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" }, "p-defer": { "version": "1.0.0", @@ -2170,13 +2411,6 @@ "requires": { "aggregate-error": "^3.0.0", "p-cancelable": "^2.0.0" - }, - "dependencies": { - "p-cancelable": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.0.0.tgz", - "integrity": "sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==" - } } }, "package-json": { @@ -2191,6 +2425,132 @@ "semver": "^6.2.0" }, "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "get-stream": { + "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" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -2240,24 +2600,23 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pg": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.3.3.tgz", - "integrity": "sha512-wmUyoQM/Xzmo62wgOdQAn5tl7u+IA1ZYK7qbuppi+3E+Gj4hlUxVHjInulieWrd0SfHi/ADriTb5ILJ/lsJrSg==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.4.1.tgz", + "integrity": "sha512-NRsH0aGMXmX1z8Dd0iaPCxWUw4ffu+lIAmGm+sTCwuDDWkpEgRCAHZYDwqaNhC5hG5DRMOjSUFasMWhvcmLN1A==", "requires": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.3.0", + "pg-connection-string": "^2.4.0", "pg-pool": "^3.2.1", - "pg-protocol": "^1.2.5", + "pg-protocol": "^1.3.0", "pg-types": "^2.1.0", - "pgpass": "1.x", - "semver": "4.3.2" + "pgpass": "1.x" } }, "pg-connection-string": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.3.0.tgz", - "integrity": "sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", + "integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==" }, "pg-hstore": { "version": "2.3.3", @@ -2278,9 +2637,9 @@ "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA==" }, "pg-protocol": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.5.tgz", - "integrity": "sha512-1uYCckkuTfzz/FCefvavRywkowa6M5FohNMF5OjKrqo9PSR8gYc8poVmwwYQaBxhmQdBjhtP514eXy9/Us2xKg==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.3.0.tgz", + "integrity": "sha512-64/bYByMrhWULUaCd+6/72c9PMWhiVFs3EVxl9Ct6a3v/U8+rKgqP2w+kKg/BIGgMJyB+Bk/eNivT32Al+Jghw==" }, "pg-types": { "version": "2.2.0", @@ -2295,11 +2654,11 @@ } }, "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", + "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", "requires": { - "split": "^1.0.0" + "split2": "^3.1.1" } }, "picomatch": { @@ -2415,9 +2774,9 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "pupa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", - "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.0.tgz", + "integrity": "sha512-Pj8EhJzFiPwnf4dEXpuUWwH8M/Yl4vpl4cN2RX1i3R77DWvbY5ZPKni7CCKkOYxz+XKt2fieemsV+WTZbIlYzg==", "dev": true, "requires": { "escape-goat": "^2.0.0" @@ -2433,6 +2792,12 @@ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", + "dev": true + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -2475,14 +2840,45 @@ } }, "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", "dev": true, "requires": { "picomatch": "^2.2.1" } }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, "registry-auth-token": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", @@ -2546,12 +2942,11 @@ "integrity": "sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA==" }, "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", "requires": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "^2.0.0" } }, "retry-as-promised": { @@ -2591,9 +2986,9 @@ "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=" }, "semver": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", - "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" }, "semver-diff": { "version": "3.1.1", @@ -2632,6 +3027,11 @@ "statuses": "~1.5.0" }, "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, "ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", @@ -2672,15 +3072,10 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" - }, "uuid": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", - "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==" + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==" } } }, @@ -2749,17 +3144,39 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "side-channel": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.3.tgz", + "integrity": "sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g==", + "dev": true, + "requires": { + "es-abstract": "^1.18.0-next.0", + "object-inspect": "^1.8.0" + } + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "requires": { - "through": "2" + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "sqlite3": { @@ -2799,43 +3216,33 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", + "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", "dev": true, "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "string.prototype.trimstart": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", + "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" } }, "string_decoder": { @@ -2847,12 +3254,11 @@ } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^2.0.0" } }, "strip-json-comments": { @@ -2885,11 +3291,6 @@ "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==", "dev": true }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -2922,6 +3323,17 @@ "dev": true, "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=", + "dev": true, + "requires": { + "abbrev": "1" + } + } } }, "tough-cookie": { @@ -2970,6 +3382,15 @@ "is-typedarray": "^1.0.0" } }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dev": true, + "requires": { + "random-bytes": "~1.0.0" + } + }, "undefsafe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", @@ -3007,9 +3428,9 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "update-notifier": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.1.tgz", - "integrity": "sha512-9y+Kds0+LoLG6yN802wVXoIfxYEwh3FlZwzMwpCZp62S2i1/Jzeqb9Eeeju3NSHccGGasfGlK5/vEHbAifYRDg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", "dev": true, "requires": { "boxen": "^4.2.0", @@ -3028,12 +3449,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -3153,47 +3573,123 @@ "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", + "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==", + "dev": true, + "requires": { + "is-bigint": "^1.0.0", + "is-boolean-object": "^1.0.0", + "is-number-object": "^1.0.3", + "is-string": "^1.0.4", + "is-symbol": "^1.0.2" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-typed-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz", + "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.2", + "es-abstract": "^1.17.5", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { "string-width": "^1.0.2 || 2" + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" }, "dependencies": { "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } } } }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" - } - }, "wkx": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", diff --git a/package.json b/package.json index 8fc414d..23f457c 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,9 @@ "sqlite3": "^5.0.0" }, "devDependencies": { + "connect-session-sequelize": "^7.0.3", "cross-env": "^7.0.2", + "express-session": "^1.17.1", "nodemon": "^2.0.1" }, "nodemonConfig": { diff --git a/routes/routes.js b/routes/routes.js index 71be56a..bd4b77c 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -1,64 +1,57 @@ -const express = require('express'); +const express = require("express"); const router = express.Router(); +const { routeRequiresSignedIn, getCurrentUserId } = require("../JS/auth-setup"); -const { User, UserAnswers } = require('../JS/orm'); +const { User, UserAnswers } = require("../JS/orm"); const ANSWER_HISTORY_LIMIT = 3; - -router.get('/', (req, res) => { - res.render('index'); +router.get("/", (req, res) => { + res.render("index"); }); -router.get('/cheatsheet', (req,res) => { - res.render('cheatsheet'); -}) +router.get("/cheatsheet", (req, res) => { + res.render("cheatsheet"); +}); -router.post('/user/answers/question/:questionNumber', (req, res) => { - if(req.body.id) { - return res.status(400).json({'message': 'ID should not be provided'}); - } - // Created won't be needed when issue #74 has been solved, should be changed by findOne and handle the errors - User.findOrCreate({ - where: {id: req.body.userId} - }).then(users => { - let user = users[0]; - - UserAnswers.create({ - user_id: user.id, - question_number: req.params.questionNumber, - is_correct: req.body.isCorrect, - elapsed_time_ms: req.body.elapsedTimeMs - }).then(userAnswer => { - return res.status(201).json(userAnswer) - }).catch(error => { - console.log(error); - return res.status(400).json(error.errors) - }) - }).catch(error => { - console.log(error); - return res.status(400).json(error.errors) +// All user-related API routes need a signed in user +router.use("/user", routeRequiresSignedIn); + +router.post("/user/answers/question/:questionNumber", (req, res, next) => { + if (req.body.id) { + return res.status(400).json({ message: "ID should not be provided" }); + } + UserAnswers.create({ + user_id: getCurrentUserId(res), + question_number: req.params.questionNumber, + is_correct: req.body.isCorrect, + elapsed_time_ms: req.body.elapsedTimeMs, + }) + .then((userAnswer) => { + res.status(201).json(userAnswer); }) -}) - -router.get('/user/answers/question/:questionNumber', (req, res) => { - // TODO: When issue #74 be done, the userId should be handled from req object - let userId = 'guest'; - - UserAnswers.findAll({ - where: {question_number: req.params.questionNumber, user_id: userId}, - order: [ - ['created_at', 'DESC'] - ], - limit: ANSWER_HISTORY_LIMIT - }).then(userAnswers => { - return res.json({ - previousTimingMs: userAnswers.map(userAnswer => userAnswer.elapsed_time_ms) - }) - }).catch(error => { - console.log(error); - return res.status(500).json(error.errors) // TODO: handle better error messages + .catch(next); +}); +router.get("/user/answers/question/:questionNumber", (req, res) => { + // TODO: When issue #74 be done, the userId should be handled from req object + let userId = "guest"; + + UserAnswers.findAll({ + where: { question_number: req.params.questionNumber, user_id: userId }, + order: [["created_at", "DESC"]], + limit: ANSWER_HISTORY_LIMIT, + }) + .then((userAnswers) => { + return res.json({ + previousTimingMs: userAnswers.map( + (userAnswer) => userAnswer.elapsed_time_ms + ), + }); }) -}) + .catch((error) => { + console.log(error); + return res.status(500).json(error.errors); // TODO: handle better error messages + }); +}); module.exports = router; diff --git a/views/index.ejs b/views/index.ejs index f739296..c42088c 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -130,6 +130,13 @@
+

+ <% if (currentUserId) { %> + You are logged in as <%= currentUserId %>. Logout + <% } else { %> + You are not logged in. Login to save your progress! + <% } %> +

This project is open-source! Look at the code and contribute here.

From 599469997fe2c2ad66c4f74e6e5e3b34e8de8115 Mon Sep 17 00:00:00 2001 From: Bill DePhillips <355438+vegetabill@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:15:37 -0700 Subject: [PATCH 51/56] Add Auth0 callback instructions (#141) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 103c1a1..21a7539 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ can sign in, practice with the app, and save their progress. That way, the next 1. Create a `Regular Web Application` 1. Run `cp .env.example .env` to create a .env file 1. From the settings page of your Auth0 web application fill in the environment variables, ensuring that the `AUTH0_ISSUER_BASE_URL` is the Domain URL starting with `https://` +1. The _Allowed Callback URLs_ for local development should be `http://localhost:3000/callback` ## Running the project From fd688c17d4f7cae751992372fe5c0ab223fd5ed3 Mon Sep 17 00:00:00 2001 From: Jackie Zhang Date: Fri, 6 Nov 2020 11:33:45 -0800 Subject: [PATCH 52/56] Add indexes: user_answers_created_at_user_id_question_number, user_answers_created_at_user_id --- JS/orm.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/JS/orm.js b/JS/orm.js index 784dabf..660ad4f 100644 --- a/JS/orm.js +++ b/JS/orm.js @@ -49,7 +49,15 @@ UserAnswers.init( sequelize, modelName: "user_answers", createdAt: 'created_at', - updatedAt: false + updatedAt: false, + indexes: [ + { + fields: ['created_at', 'user_id', 'question_number'] + }, + { + fields: ['created_at', 'user_id'] + } + ] } ); User.hasMany(UserAnswers, {foreignKey: 'user_id'}); From 35e22606e052440479a66c661462af7366f01464 Mon Sep 17 00:00:00 2001 From: Bill DePhillips <355438+vegetabill@users.noreply.github.com> Date: Sun, 6 Dec 2020 18:13:34 -0800 Subject: [PATCH 53/56] Integrate all auth-dependent API stories into working app version (#142) * Fixes #74 - fake login/logout for local dev - refactor auth setup so it is the same for the rest of the code regardless if it's fake dev or Auth0 - use express-session with sequelize store to handle sessions (they will persist dev reload) - add dummy login state message to bottom of index page so dev can use login/logout before buttons are added * make .env.example a little more user-friendly * add .git.local ignore so it can be used to switch between Auth0 and local dev without accidentally checking it in * Fully integrate Auth0 and local dev - Auth create user upon login or root request - Protect all /user API routes to need a valid signed-in user or they will respond with 401 - fix ORM data models so they have default values and work correctly with postgres * fix comments * do not save or fetch data unless logged in * fix get history endpoint to lookup by logged in user id from request * Implements #77 - replaces all localStorage lookups with saved /user/progress API call - remove commented code - add const/let variable declarations when missing * Add API integration specs using jasmine + supertest --- JS/config.js | 3 +- app.js | 2 + package-lock.json | 125 ++++++++++++++++++++++++++++++++ package.json | 7 +- public/scripts/history.js | 4 +- public/scripts/main.js | 136 ++++++++++++++++------------------- routes/routes.js | 21 ++++-- spec/api-integration-spec.js | 51 +++++++++++++ spec/support/jasmine.json | 11 +++ views/index.ejs | 3 + 10 files changed, 276 insertions(+), 87 deletions(-) create mode 100644 spec/api-integration-spec.js create mode 100644 spec/support/jasmine.json diff --git a/JS/config.js b/JS/config.js index 91c92a1..43fc04e 100644 --- a/JS/config.js +++ b/JS/config.js @@ -6,10 +6,9 @@ const isProduction = () => NODE_ENV === "production"; const isDevelopment = () => NODE_ENV === "development"; const getDefaultDbUrl = () => { - if (isDevelopment()) { + if (!isProduction()) { return "sqlite:dev-db.sqlite"; } - throw new Error("DB_URL must be specified in production mode"); }; module.exports = { diff --git a/app.js b/app.js index aeac87b..ea12494 100644 --- a/app.js +++ b/app.js @@ -36,3 +36,5 @@ const startServer = async () => { }; startServer(); + +module.exports = app; diff --git a/package-lock.json b/package-lock.json index 4d0dd89..2634a61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -599,6 +599,12 @@ "delayed-stream": "~1.0.0" } }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -673,6 +679,12 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1151,6 +1163,12 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "dev": true + }, "filelist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", @@ -1208,6 +1226,12 @@ "mime-types": "^2.1.12" } }, + "formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "dev": true + }, "forwarded": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", @@ -1785,6 +1809,22 @@ "minimatch": "^3.0.4" } }, + "jasmine": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.6.2.tgz", + "integrity": "sha512-Uc0o2MRnC8TS1MjDrB8jE1umKEo2mflzGvdg0Ncs+yuLtOJ+uz/Wz8VmGsNGtuASr8+E0LDgPkOpvdoC76m5WQ==", + "dev": true, + "requires": { + "glob": "^7.1.6", + "jasmine-core": "~3.6.0" + } + }, + "jasmine-core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", + "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", + "dev": true + }, "jose": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.2.tgz", @@ -3266,6 +3306,91 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, + "superagent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", + "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", + "dev": true, + "requires": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.2", + "methods": "^1.1.2", + "mime": "^2.4.6", + "qs": "^6.9.4", + "readable-stream": "^3.6.0", + "semver": "^7.3.2" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "form-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", + "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "supertest": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-5.0.0.tgz", + "integrity": "sha512-2JAWpPrUOZF4hHH5ZTCN2xjKXvJS3AEwPNXl0HUseHsfcXFvMy9kcsufIHCNAmQ5hlGCvgeAqaR5PBEouN3hlQ==", + "dev": true, + "requires": { + "methods": "1.1.2", + "superagent": "6.1.0" + } + }, + "supertest-session": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/supertest-session/-/supertest-session-4.1.0.tgz", + "integrity": "sha512-zJmc2+WBpT772Pk6InGg90n0l1E+8rr5ue8PAyxefIEJWqbrn0RC02brrw7EC1wecoY+UH/AaQxMeo3sPrnPPA==", + "dev": true, + "requires": { + "cookiejar": "^2.1.2", + "methods": "^1.1.2", + "object-assign": "^4.0.1" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", diff --git a/package.json b/package.json index 23f457c..39d99cc 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "start": "cross-env npm run dev", "start:prod": "cross-env NODE_ENV=production node app.js", "dev": "cross-env NODE_ENV=development nodemon", - "test": "mocha" + "test": "npx jasmine" }, "repository": { "type": "git", @@ -40,7 +40,10 @@ "connect-session-sequelize": "^7.0.3", "cross-env": "^7.0.2", "express-session": "^1.17.1", - "nodemon": "^2.0.1" + "jasmine": "^3.6.2", + "nodemon": "^2.0.1", + "supertest": "^5.0.0", + "supertest-session": "^4.1.0" }, "nodemonConfig": { "execMap": { diff --git a/public/scripts/history.js b/public/scripts/history.js index e3516e0..f464c51 100644 --- a/public/scripts/history.js +++ b/public/scripts/history.js @@ -2,10 +2,8 @@ // returns an array with timing data for a given question number async function getHistory(questionNo) { - let url = new URL(document.URL + 'user/answers/question/' + questionNo); - try{ - let response = await fetch(url); + let response = await fetch(`/user/answers/question/${questionNo}`); let body = await response.json(); return body.previousTimingMs; diff --git a/public/scripts/main.js b/public/scripts/main.js index 6c43034..10fb23a 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -37,34 +37,39 @@ const keyToId = { 'underscore(_)': 'minus' }; +// Since we are not using localStorage anymore, this is a one-time clear +localStorage.clear(); +// These variables used to be stored in localStorage +let questionNo = 1; +let totalCount; + // this tracks when we started asking for the current key command let questionStartMS = 0; -$(document).ready(function() { - //$("#retryButton").toggleClass("on"); - //alert($('li[data-keycode="test"]').attr('id')); - fetch('scripts/shortcuts.json') - .then(response => response.json()) - .then(data => { - allData=data - if(localStorage.getItem("questionNo")==null) - { - localStorage.setItem("questionNo", "1"); - localStorage.setItem("totalCount", Object.keys(allData).length); - } - readText() - updateTimingDisplay() - }); + +document.addEventListener("DOMContentLoaded", () => { + fetch("scripts/shortcuts.json") + .then((response) => response.json()) + .then((data) => { + allData = data; + totalCount = Object.keys(allData).length; + if (window.isLoggedIn) { + return getSavedProgress().then((progressData) => { + questionNo = progressData.currentQuestionNumber; + }); + } + }).then(() => { + readText(); + updateTimingDisplay(); + }) + }); function nextQuestion() { - if(localStorage.getItem("questionNo")!=null){ - if(parseInt(localStorage.getItem("questionNo")) 1) { - localStorage.setItem("questionNo", parseInt(localStorage.getItem("questionNo"))-1); - } + if (questionNo === 1) { + return; } + questionNo -= 1; clearPromptKeys(); clearPressedKeys(); updateTimingDisplay(); @@ -192,7 +196,7 @@ function promptKey2(key){ function promptKey(key){ // Handling all key types key = key.toLowerCase(); - id = key.length == 1 ? key : keyToId[key]; + const id = key.length == 1 ? key : keyToId[key]; if (id) document.querySelector('#' + id).classList.toggle('prompt'); } @@ -201,51 +205,27 @@ function promptKey(key){ * @param withoutAnimation {boolean=} [withoutAnimation = false] flag to prevent typing question animation */ function readText(withoutAnimation){ - quesNo = localStorage.getItem("questionNo") - if(quesNo!=null){ - commandText = allData[parseInt(quesNo)-1].answer - answerkeys = allData[parseInt(quesNo)-1].keys - type = allData[parseInt(quesNo) - 1].shortcutType - //commandText = "A+Control" // document.querySelector("#textdiv").textContent; // Will be taken from some other list type of a source. - //Each command will have an associated question text used in writeQuestion - var speed = 50 - var i = 0; + const questionIdx = questionNo - 1; + const { question, keys, shortcutType } = allData[questionIdx]; // Call writeQuestion to add question on the top textarea if (!withoutAnimation) { - writeQuestion(allData[parseInt(localStorage.getItem("questionNo"))-1].question) + writeQuestion(question); } - $.each(answerkeys , function(index, val) { + keys.forEach((val) => { reqKeys.push(val) // Highlight the prompt keys promptKey2(val) }); // update shortcut type - document.querySelector("#shortcut-tag").textContent = type + " Shortcut"; - if(type == 'mac') { + document.querySelector("#shortcut-tag").textContent = shortcutType + " Shortcut"; + if(shortcutType === 'mac') { $('#shortcut-tag').first().css('background-color', '#3455db') } else { $('#shortcut-tag').first().css('background-color', '#4b2142') } - - /* commandText.split('+').forEach(function(c) { - if(c.toLowerCase()=="command"){ - reqKeys.push("meta") - }else if(c.toLowerCase()=="option"){ - reqKeys.push("alt") - } - else{ - reqKeys.push(c) - } -// Highlight the prompt keys - promptKey(c) - - }); */ - - //key(commandText, function(){ onSuccess(...reqKeys)}); - } // END IF for localStorage check } function writeQuestion(question) { @@ -283,20 +263,21 @@ function clearPressedKeys() { function updateTimingDisplay() { $('#timing-feedback').html(''); - var questionNo = localStorage.getItem('questionNo'); + // hide the boxes if we don't have timing data + for (var i = 0; i < 3; i++) { + $('#timing-' + i).hide(); + } + if (!window.isLoggedIn) { + return; + } // grab the last bits of timing data getHistory(questionNo).then(timings => { // and then drop them into the boxes timings.forEach(function(t, idx) { - var element = $('#timing-' + idx); + const element = $('#timing-' + idx); element.html(t / 1000 + ' sec'); element.show(); }) - - // hide the boxes if we don't have timing data - for (var i = timings.length; i < 3; i++) { - $('#timing-' + i).hide(); - } }); } @@ -308,6 +289,9 @@ function onIncorrect() { }; function handleTimingFeedback(questionNo, curMS) { + if (!window.isLoggedIn) { + return; + } getHistory(questionNo).then(previousTimings => { if (previousTimings.length == 0) { return; @@ -343,8 +327,7 @@ function handleTimingFeedback(questionNo, curMS) { // Function to execute when correct keys are pressed. function onSuccess() { - var questionNo = localStorage.getItem("questionNo"); - var thisAnswerMS = Date.now() - questionStartMS; + const thisAnswerMS = Date.now() - questionStartMS; handleTimingFeedback(questionNo, thisAnswerMS); document.querySelector("#textdiv span").textContent = 'Correct Keys pressed!'; clearPromptKeys(); @@ -357,11 +340,6 @@ function onSuccess() { document.addEventListener('keydown', function(event) { event.preventDefault(); clearIncorrectIndication(); - if(localStorage.getItem("questionNo")!=null){ - if(quesNo!=localStorage.getItem("questionNo")){ - return; - } - } // If used in Firefox, change command key code to be the same as that of Chrome let keyCode = event.keyCode; @@ -391,11 +369,6 @@ document.addEventListener('keydown', function(event) { document.addEventListener('keyup', function(event) { event.preventDefault(); - if(localStorage.getItem("questionNo")!=null){ - if(quesNo!=localStorage.getItem("questionNo")) { - return; - } - } // If used in Firefox, change command key code to be the same as that of Chrome let keyCode = event.keyCode; @@ -430,6 +403,9 @@ showHintCheckbox.addEventListener('change', function(e) { }) function createUserAnswer(questionNo, isCorrect, elapsedTimeMs){ + if (!window.isLoggedIn) { + return; + } let requestBody = { userId: 'guest', isCorrect: isCorrect, @@ -446,4 +422,14 @@ function createUserAnswer(questionNo, isCorrect, elapsedTimeMs){ // TODO: handle error messages in a better way console.log(error); }) +} + +function getSavedProgress() { + return fetch('/user/progress').then(resp => { + if (resp.ok) { + return resp.json(); + } else { + throw new Error(`Unable to retrieve saved progress. Received ${resp.status}`); + } + }) } \ No newline at end of file diff --git a/routes/routes.js b/routes/routes.js index bd4b77c..6db7280 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -2,7 +2,7 @@ const express = require("express"); const router = express.Router(); const { routeRequiresSignedIn, getCurrentUserId } = require("../JS/auth-setup"); -const { User, UserAnswers } = require("../JS/orm"); +const { UserAnswers } = require("../JS/orm"); const ANSWER_HISTORY_LIMIT = 3; @@ -17,6 +17,20 @@ router.get("/cheatsheet", (req, res) => { // All user-related API routes need a signed in user router.use("/user", routeRequiresSignedIn); +router.get("/user/progress", (_, res, next) => { + UserAnswers.findOne({ + where: { + user_id: getCurrentUserId(res), + }, + order: [["created_at", "DESC"]], + }) + .then((answer) => { + const currentQuestionNumber = answer ? answer.question_number + 1 : 1; + res.send({ currentQuestionNumber }); + }) + .catch(next); +}); + router.post("/user/answers/question/:questionNumber", (req, res, next) => { if (req.body.id) { return res.status(400).json({ message: "ID should not be provided" }); @@ -33,11 +47,8 @@ router.post("/user/answers/question/:questionNumber", (req, res, next) => { .catch(next); }); router.get("/user/answers/question/:questionNumber", (req, res) => { - // TODO: When issue #74 be done, the userId should be handled from req object - let userId = "guest"; - UserAnswers.findAll({ - where: { question_number: req.params.questionNumber, user_id: userId }, + where: { question_number: req.params.questionNumber, user_id: getCurrentUserId(res) }, order: [["created_at", "DESC"]], limit: ANSWER_HISTORY_LIMIT, }) diff --git a/spec/api-integration-spec.js b/spec/api-integration-spec.js new file mode 100644 index 0000000..dfeca73 --- /dev/null +++ b/spec/api-integration-spec.js @@ -0,0 +1,51 @@ +const request = require("supertest"); +const session = require("supertest-session"); +const app = require("../app"); +const { connectToDb, UserAnswers } = require("../JS/orm"); + +describe("User API", () => { + beforeAll(() => connectToDb()); + beforeEach(() => UserAnswers.truncate()); + + describe("when logged in", () => { + let signedInSession; + + beforeEach(() => { + signedInSession = session(app); + return signedInSession.get("/login").expect(302); + }); + + it("should have default of first question", () => { + return signedInSession + .get("/user/progress") + .expect(200, { currentQuestionNumber: 1 }); + }); + + it("should update progress when an answer is saved", async () => { + await signedInSession + .post("/user/answers/question/5") + .send({ isCorrect: true, elapsedTimeMs: 150 }) + .expect(201); + return signedInSession + .get("/user/progress") + .expect(200, { currentQuestionNumber: 6 }); + }); + + it("should return up to 3 previous question timings for a question", async () => { + for (let i = 1; i <= 4; i++) { + await signedInSession + .post("/user/answers/question/7") + .send({ isCorrect: true, elapsedTimeMs: 100 * i }); + } + + return signedInSession.get("/user/answers/question/7").expect(200, { + previousTimingMs: [400, 300, 200], + }); + }); + }); + + describe("when not logged in", () => { + it("should respond with 401", () => + request(app).get("/user/progress").expect(401)); + }); +}); diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json new file mode 100644 index 0000000..370fc44 --- /dev/null +++ b/spec/support/jasmine.json @@ -0,0 +1,11 @@ +{ + "spec_dir": "spec", + "spec_files": [ + "**/*[sS]pec.js" + ], + "helpers": [ + "helpers/**/*.js" + ], + "stopSpecOnExpectationFailure": false, + "random": true +} diff --git a/views/index.ejs b/views/index.ejs index c42088c..464040c 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -11,6 +11,9 @@ + From baeab7fac570f3e9f2053dbef10819861b421894 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 13 Dec 2020 15:23:31 -0800 Subject: [PATCH 54/56] Bump ini from 1.3.5 to 1.3.8 (#145) Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8. - [Release notes](https://github.com/isaacs/ini/releases) - [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2634a61..3b28de9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1565,9 +1565,9 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "ipaddr.js": { "version": "1.9.1", From 8bc660359d88b1f0033342ea7b5f03b62c1c87e1 Mon Sep 17 00:00:00 2001 From: Jackie Zhang Date: Sat, 30 Oct 2021 11:00:25 -0700 Subject: [PATCH 55/56] Login button shows correct status centered (#146) * - Add login and logout buttons to the top of the main page * - Adjust account-info's margins * - 2nd draft of login button. Account info is centered in the whitespace above the read container Co-authored-by: Jackie Zhang --- public/CSS/main.css | 37 +++++++++++++++++++++++++++++++++++++ views/index.ejs | 8 ++++++++ 2 files changed, 45 insertions(+) diff --git a/public/CSS/main.css b/public/CSS/main.css index 914aba1..b6bf6d3 100644 --- a/public/CSS/main.css +++ b/public/CSS/main.css @@ -15,6 +15,19 @@ width: 800px; } +.center-column { + width: 690px; +} + +.log-button { + border-radius: 5px; + font-size: 12px; + padding: 3px 10px; + text-align: center; + text-transform: capitalize; + text-decoration: none; +} + body { font: 71%/1.5 Verdana, Sans-Serif; color: #37474F; @@ -226,4 +239,28 @@ div .arrows{ #hint-checkbox-container #show-hint { height: 1rem; width: 1rem; +} + +#account-info { + display: flex; + justify-content: flex-end; + align-items: center; + font-size: 0.8rem; + margin: -37.5px 0px 32.5px 0px; +} + +#login-button { + color: #28a7c5; + background-color: #ffffff; + border: 1px solid #28a7c5; +} + +#logout-button { + color: #ffffff; + background-color: #28a7c5; + border: 1px solid #28a7c5; +} + +#login-indicator { + margin: 0rem 0.5rem; } \ No newline at end of file diff --git a/views/index.ejs b/views/index.ejs index 464040c..0883945 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -19,6 +19,14 @@
+
+ <% if (currentUserId) { %> + Logged in + Logout + <% } else { %> + Login + <% } %> +
From b5c1c2d0643818269afe38cc5b824f6461345870 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 30 Oct 2021 11:01:07 -0700 Subject: [PATCH 56/56] Bump jose from 2.0.2 to 2.0.5 (#148) --- CONTRIBUTING.md | 3 ++- README.md | 1 + package-lock.json | 6 +++--- public/scripts/main.js | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 956b9a9..5d4cfb2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,7 @@ Prepare for contributing by following these beginner-friendly steps. 1. Run `git checkout backend` to go to the backend feature branch. This is the *only* branch that we will be working in. 1. Follow [the steps to run the project locally](/README.md/#running-the-project). 1. Run `git remote add upstream https://github.com/Techtonica/keyboard-shortcuts-practice.git`. This is so that you can refer to the original project owned by Techtonica as the `upstream` version. -1. Run `git remote -v` to test that you can get updates from Techtonica's repo. [You should see something like this](https://github.com/anitab-org/mentorship-android/wiki/Fork,-Clone-&-Remote#remote). If it shows an error that you don't have permission, contact a Tectonica admin. You can still get started without this part, but you'll need it soon. +1. Run `git remove -v` to test that you can get updates from Techtonica's repo. [You should see something like this](https://github.com/anitab-org/mentorship-android/wiki/Fork,-Clone-&-Remote#remote). If it shows an error that you don't have permission, contact a Tectonica admin. You can still get started without this part, but you'll need it soon. ### Get started 1. Choose an issue in the "To Do" column of [this board](https://github.com/Techtonica/keyboard-shortcuts-practice/projects/4). @@ -32,3 +32,4 @@ Prepare for contributing by following these beginner-friendly steps. making a pull request to the backend branch 1. See your pull requests here: https://github.com/Techtonica/keyboard-shortcuts-practice/pulls 1. In your new PR's description, add `Fixes #`, for example `fixes #1`. This will automatically close the issue once your PR is merged, and it will link the issue with your PR. Also add a description of what the PR is, and how reviewers can validate it. + diff --git a/README.md b/README.md index 21a7539..bd738bb 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ can sign in, practice with the app, and save their progress. That way, the next 1. Run `npm start` to start the server. 1. Navigate to `http://localhost:3000` in your browser. Your project should be running at this point. + ## Contributing / Volunteering Go to [CONTRIBUTING.md](/CONTRIBUTING.md). diff --git a/package-lock.json b/package-lock.json index 3b28de9..ccec227 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1826,9 +1826,9 @@ "dev": true }, "jose": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.2.tgz", - "integrity": "sha512-yD93lsiMA1go/qxSY/vXWBodmIZJIxeB7QhFi8z1yQ3KUwKENqI9UA8VCHlQ5h3x1zWuWZjoY87ByQzkQbIrQg==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz", + "integrity": "sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA==", "requires": { "@panva/asn1.js": "^1.0.0" } diff --git a/public/scripts/main.js b/public/scripts/main.js index 10fb23a..2bf3a87 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -432,4 +432,4 @@ function getSavedProgress() { throw new Error(`Unable to retrieve saved progress. Received ${resp.status}`); } }) -} \ No newline at end of file +}